git删除历史记录中的大文件

找出大文件的 pack 记录,取排名前3的,执行以下命令:
git verify-pack -v .git/objects/pack/pack-*.idx | sort -k 3 -g | tail -3

上面的命令执行后出现如下信息:
a8fd323c1a55f4bbaa43035605a87a55f8f85d27 blob   5298413 5183208 3901484
4aff67933565086f46576eabc761fcaacb562cb8 blob   11441096 3770239 13418161
a16bc0a3a3fefa5ec5a224fc24f837a18703c25d blob   12814440 4333469 9084692

最后一条就是最大的一条记录,第一列是id

找出该记录对应的文件,执行以下命令:
git rev-list --objects --all | grep a16bc0a3a3fefa5ec5a224fc24f837a18703c25d

执行后出现如下信息:
a16bc0a3a3fefa5ec5a224fc24f837a18703c25d xxxx.bin

将该文件从历史记录中删除,执行以下命令:
git log --pretty=oneline --branches -- xxxx.bin

上面的命令执行后只是从历史记录中移除,还没有完全删除它,我们需要重写所有 commit,将该文件从 Git 历史中完全删除:
git filter-branch --index-filter 'git rm --cached --ignore-unmatch xxxx.bin -- --all'

上面的命令执行后,此时历史记录中已经没有该文件了,此时是真正删除了它。

不过我们运行 filter-branch 产生的日志还是会对该文件有引用,所以我们还需要运行以下几条命令,把该文件的引用完全删除:
rm -Rf .git/refs/original
rm -Rf .git/logs/
git gc
git prune

最后一步就是 push 代码了,不过就是需要强制 push:
git push --force