14

I accidentally tracked workspace configuration files in a git repo. Trying to fix the problem, I git rm --cached those files and added them to .gitignore file.

Now every time I checkout a branch from the repo, those get deleted. Is there any way to avoid this?

Gabriele Petronella
  • 106,943
  • 21
  • 217
  • 235
aitkiar
  • 273
  • 1
  • 3
  • 12

1 Answers1

16

The problem is the git rm commit being present in some branches but not all, which means that when you switch from one branch still containing the files to one where you git rm'ed git will correctly remove the files. What you actually want to do is remove the files from git's history as if they have never been there, following this question. You should however be aware that this means rewriting the repository history, so for one thing you will have to git push --force afterwards, and for another thing, you will upset others who also work with this repo.

edit Should rewriting history not be viable, make sure you commit the git rm --cached action on every branch existing. You will however still encounter unpleasant re-deletion should you checkout revisions before that deletion.

Summary:

  • commit a .gitignore + git rm --cached to each branch if history cannot be rewritten, but remember that checking out any previous revision (e.g. via a tag) will a) yield an error about the existing untracked files git wants to checkout and b) cause another deletion of these files on switching back to HEAD
  • rewrite history if you are likely to checkout previous revisions often (or some of the files accidentally committed contain sensitive data) to avoid this, but be aware that this will screw up everyone else's clone

In fact, there is a third possibility: For each branch, create a new branch in which you rewrite history, while to the original version add one commit removing all files (except the to be ignored ones!1) adding a highly visible file explaining the mess-up and asking users to switch to the rewritten branch from now on and remove their local copy of the unrewritten one.


1The reason for this is you don't want to delete other users' version of these files that shouldn't have been versioned from the very start, and since one is not expected to ever switch back to the old version this will never yield said "file already exists" error

Community
  • 1
  • 1
Tobias Kienzler
  • 25,759
  • 22
  • 127
  • 221
  • Please clarify that this isn't about deleting the files from the history, but about having `.gitignore` consistent across branches. – Yuval Adam Aug 27 '13 at 12:40
  • @YuvalAdam It _is_ about deleting the files from the history - they should never have been there to start with, and putting them in `.gitignore` across branches won't fix the deletion-on-branch-change issue (though a `git rm` + `.gitignore` commit on _each_ branch will, and should be preferred if many users access the repo, even at the expense of a dirty history...) – Tobias Kienzler Aug 27 '13 at 12:56
  • diferent .gitignore in different branches is the first thing I corrected. But it didn't fix the problem. – aitkiar Aug 27 '13 at 12:57
  • @aitkiar You'll also have to make a `git rm --cached` commit on each branch, since otherwise another branch, while ignoring the files, still tracks them and when git switches to one where you `git rm`'ed, it will think "ok, now I'm switching from a branch where the files still exist to one where they don't, so I have to remove them". As said, the "cleaner" solution would be rewriting history so the files appear to have never been tracked, but whether that is an option for you depends on who else accesses the repo – Tobias Kienzler Aug 27 '13 at 13:04
  • @TobiasKienzler Your workaround proves my points, you don't need to delete from history, just delete from working copies and ignore. Furthermore, in many repositories, history rewrites are absolutely unacceptable. So the only reasonable option is to forward-delete and ignore on master and all (relevant) branches. – Yuval Adam Aug 27 '13 at 21:10
  • @YuvalAdam Partly agreed - rewriting history is a severe modification that should be thoroughly reflected upon. But as mentioned, if you use the workaround instead, checking out a pre-deletion revision will a) result in a "this file already exists" error and b) cause the files to be removed once switching back to the branch head. But as you said, this might be a lesser evil compared to a complete history rewrite. – Tobias Kienzler Aug 28 '13 at 06:05
  • @YuvalAdam In fact, there's a third possibility I edited in: Create a new branch with rewritten history and have the old branch indicate this clearly – Tobias Kienzler Aug 28 '13 at 06:18