0

Background

I'm migrating a VCS to git. This is done by checking out from the old VCS (TFSVC) and checking into a git repository via scripts.

Essentially in such a loop:

for x in $(seq 1 100)
do
  tf get $x  # get version x
  git add .  # add everything to index
  git commit # commit
done

Problem

The old VCS contains a .gitignore, as a part of the migration process, I don't want these patterns to apply. This can easily be fixed using git add . --force. The problem is that there are still things that I may want to ignore.

What I've tried

I was hoping to use .git/info/exclude for the purpose, but git-add --force apparently ignores this in addition to .gitignore rules. It seems the same goes for core.excludesFile.

Ideal solution

  • Exclude the rules of .gitignore
  • Use the rules in .git/info/exclude or some other exclude file or pattern
  • Somewhat performant, the process is slow enough as it is
  • Doesn't rely on modifying the working tree

An option is of-course to simply git restore --staged $EXCLUDE_PATH_SPEC after adding everything to the index but I'm wondering if there isn't a better solution.

I seem to recall seeing an option for specifying an ignore/exclude glob but I can't seem to be able to find it.

Maybe there's a way to achieve this using a plumbing commands, like git update-index?


Edit

I've added clarification that I'd rather not rely on a solution that modifies the working tree (ie: moving/modifying .gitignore) since it's been suggested multiple times. Mainly because of these reasons:

  1. There are nested .gitignore files
  2. Their existence and contents rely on the state of the other VCS, I want to be in full control
  3. There is another VCS tracking the files and so anything modifying the working tree, besides the incremental fetching from the other VCS complicates matters
  4. It's in all likelihood slower (although maybe not slow enough to be a major concern)
CervEd
  • 3,306
  • 28
  • 25
  • 3
    Couldn't you just do `cp /path/to/my/ignore/file .gitignore` after the `tf get` step? – Thomas May 05 '21 at 11:58
  • @Thomas that modifies the working tree, I'd rather avoid such a solution – CervEd May 05 '21 at 12:08
  • @CervEd There is no way to ignore `.gitignore` – phd May 05 '21 at 12:50
  • Look for some sort of migration software; if none exist, consider trying your hand at your own. Use `git fast-import` to create commits. This is a usually a big job though. – torek May 05 '21 at 12:59
  • @phd, yes there is `git add --force` – CervEd May 05 '21 at 13:00
  • @torek, thanks for the advice but scripting works well enough – CervEd May 05 '21 at 13:05
  • @CervEd Ok, there is no way to ignore only `.gitignore` but not all other exclude/ignore files. – phd May 05 '21 at 13:12
  • @phd, sorry but I'm not sure I understand what you're hoping to add with your comments – CervEd May 05 '21 at 13:39
  • @CervEd I hope you'd get that overwriting `.gitignore` is the simplest and the most reliable solution. – phd May 05 '21 at 14:00
  • @phd that would be a solution, however, in this use case I obviously really want to avoid making modifications to the working tree – CervEd May 05 '21 at 14:05
  • @CervEd By using `.git/info/exclude` you don't include everything from TFSVC anyway so I don't understand your desire to preserve `.gitignore` at all cost. – phd May 05 '21 at 14:13
  • @phd because I'm dealing with two version control systems, which share the same working directory, and so I'd like to avoid making changes to the working directory and avoid the headaches that come with that – CervEd May 05 '21 at 14:26

4 Answers4

2

If the standard conveniences aren't what you want, make your own with core commands. git ls-files lets you build your exclusions as you like, and git update-index will take anything you want.

git ls-files -ocX /path/to/my/excludes \
| git update-index --add --remove --stdin
git ls-files git update-index
  • --add If a specified file isn’t in the index already then it’s added.
  • --remove If a specified file is in the index but is missing then it’s removed.
  • --stdin Instead of taking list of paths from the command line, read list of paths from the standard input
CervEd
  • 3,306
  • 28
  • 25
jthill
  • 55,082
  • 5
  • 77
  • 137
  • Thanks! This is exactly what I was looking for. I suggested an edit with links to the docs of the options as well as short explanations of what they do, hope you don't mind – CervEd May 05 '21 at 21:05
1

What about temporary removing .gitignore?

for x in $(seq 1 100)
do
  tf get $x
  mv .gitignore /tmp/
  git add .
  mv /tmp/.gitignore .
  git add .gitignore
  git commit -m commit$x
done
phd
  • 82,685
  • 13
  • 120
  • 165
  • I think you mean to propose to temporarily replace the `.gitignore`, no? – CervEd May 05 '21 at 14:28
  • @CervEd That's possible if you need it. And you still can use `.git/info/exclude`. – phd May 05 '21 at 14:46
  • okay I see now, your proposed solution is to move the `.gitignore` so that only the rules in `.git/info/exclude` and `core.excludeFile` would be used. That could work in some scenarios, but like I said, I'd really like to avoid making changes to the working tree. – CervEd May 05 '21 at 15:04
  • @CervEd The code restores `.gitignore`. Even add it — just in case. – phd May 05 '21 at 15:06
  • right I know that, but in my case there are **two** VCS here that share the same working directory. You're forgetting about the other one. Like I've said, many times, this is a route I want to avoid – CervEd May 05 '21 at 15:18
  • @CervEd I don't see how it's relevant. After the 2nd `mv` the worktree is restored to its exact state so `tf` doesn't see any difference. – phd May 05 '21 at 15:40
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/231987/discussion-between-cerved-and-phd). – CervEd May 05 '21 at 15:45
0

So far the best solution I've come up with is probably using xargs and :! exclude paths.

grep --invert-match '^#' < .git/info/exclude |\
 sed 's/^/:!/' |\
 xargs git add --all --force --

It'll probably work fine enough for my use case but I'm not sure it's the best solution. I don't know how it's going to handle complicated rules, when xargs is going to blow up git add etc. Hoping someone else can come up with a better answer.

CervEd
  • 3,306
  • 28
  • 25
-2

If you want to ignore few file in git you can do below commands-

git rm -r --cached  .
git  add  .
git  commit  -m  ".gitignore is now working"

click here for details

sanjeevjha
  • 1,439
  • 14
  • 18