Git: How to remove file from historical commit?

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

Leave a Comment