Git: How to remove file from historical commit?
You will need to git rebase in the interactive mode see an example here: How can I remove a commit on GitHub? and how to remove old commits.
If your commit is at HEAD minus 10 commits:
$ git rebase -i HEAD~10
After the edition of your history, you need to push the "new" history, you need to add the +
to force (see the refspec in the push options):
$ git push origin +master
If other people have already cloned your repository, you will to inform them, because you just changed the history.
I tried using the following answer on windows https://stackoverflow.com/a/8741530/8461756
Single quote does not work on windows; you need double-quotes.
Following worked for me.
git filter-branch --force --index-filter "git rm --cached --ignore-unmatch PathRelativeRepositoryRoot/bigfile.csv" -- --all
After removing the big file, I was able to push my changes to GitHub master.
You can use git-extras tool. The obliterate command completely remove a file from the repository, including past commits and tags.
https://github.com/tj/git-extras/blob/master/Commands.md
Chapter 9 of the Pro Git book has a section on Removing Objects.
Let me outline the steps briefly here:
git filter-branch --index-filter \
'git rm --cached --ignore-unmatch path/to/mylarge_50mb_file' \
--tag-name-filter cat -- --all
Like the rebasing option described before, filter-branch
is rewriting operation. If you have published history, you'll have to --force
push the new refs.
The filter-branch
approach is considerably more powerful than the rebase
approach, since it
- allows you to work on all branches/refs at once,
- renames any tags on the fly
- operates cleanly even if there have been several merge commits since the addition of the file
- operates cleanly even if the file was (re)added/removed several times in the history of (a) branch(es)
- doesn't create new, unrelated commits, but rather copies them while modifying the trees associated with them. This means that stuff like signed commits, commit notes etc. are preserved
filter-branch
keeps backups too, so the size of the repo won't decrease immediately unless you expire the reflogs and garbage collect:
rm -Rf .git/refs/original # careful
git gc --aggressive --prune=now # danger