How to exclude files in Git while disregarding .gitignore?

434 views Asked by At

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)
4

There are 4 answers

1
jthill On BEST ANSWER

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
7
phd On

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
2
sanjeevjha On

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

0
CervEd On

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.