0

A few commits after developing a .NET project, I realized that I don't want to be tracking any of the contents of bin, obj or packages folders, and also I don't want to be tracking any files of the form *.suo or *.user. So I created a text file named .gitignore that contains those as lines and I saved the file in the root directory of my repository. Now what I want to do is retroactively remove those from the history, or if I can't do that, at least get them out of my next commit. I tried running

git rm -r --cached bin/

as suggested on Ignoring a directory from a Git repo after it's been added and I get

fatal: pathspec bin/ did not match any files

How do I fix this, or is there an easier command that would retroactively remove all these from being tracked?

Community
  • 1
  • 1
user7127000
  • 3,143
  • 6
  • 24
  • 41
  • If `git rm -r --cached bin/` says "did not match any files", there are no files in the index named `bin/` relative to your *current directory*. There may be files in *other* directories. You can use `git ls-files` to see the name of every file in the index (although you must run this from the top level of the repository to get that result). – torek Mar 22 '17 at 15:04
  • @Algorithmic - Which part of the stated problem do you mean to address with this? The problem isn't how to ignore the files, it's how to clean up the existing content of the repo. Patterns in `./git/info/exclude` will not behave any differently than those in `.gitignore` – Mark Adelsberger Mar 22 '17 at 15:26

1 Answers1

0

You can retroactive remove the files if you want, but there are caveats. For a small repo that only you access, it's no big deal; the larger the repo (mostly meaning number of commits) or the more people who use it, the bigger the potential hassle.

The basic procedure would look something like this:


1) Everyone who has a copy of the repo should commit and push any changes they want to preserve. These don't have to be merged, but they should be pushed to origin. (Any change not in origin would have to be migrated after the fact - a procedure that is straightforward but not trivial - or simply redone.) Everyone should then pause development and discard their local clones of the repo.

2) Perform the history rewrite. For a small repo this could be done with git filter-branch using an index filter like git rm --cached --ignore-unmatch -- <pathspecs>. A faster option, especially for large repos, would be the BFG repo cleaner.

(There are good usage documents for both of these options, so I won't go into great detail about both of them just now. But if you have specific follow-up questions feel free to ask of course.)

Whichever tool you use will "rewrite history" in your repo. This means that the existing commits - likely all of them based on your use case - will be replaced with new commits. (By "new commit" I mean the commits will have new SHA1 identifiers and git will not recognize them as being related to the old commits.) This is why everyone had to ditch their old clones.

3) Publish the rewritten origin (by whatever means you had previously published the original).

Everyone can now clone the rewritten repo and work can resume.


Honestly it's a pretty drastic step. It's good to know you can do it if someone accidentally commits a file containing a password or other sensitive information. Or if you can actually save considerable space in the repo by removing unwanted content like copies of dependencies. For this... I wouldn't think it's worth it.

To just remove the files from subsequent commits (so that .gitignore can be effective) the command you're using should work, assuming you're in the directory that contains the bin/ directory.

Mark Adelsberger
  • 42,148
  • 4
  • 35
  • 52