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
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…