多年以前,手滑将一张个人照片传到了公司的git项目上(我至今也回忆不起是如何做到的),紧张的立马在git删除了该文件就以为万事大吉,可当时还是太年轻,其实该照片已经永久的存在于提交记录之中了,而且还会一直占用仓库容量,即使你删除了那次的commit,只要其他commit携带了那一次的提交,就会在其他commit中出现。由此总结下git如何彻底删除某个文件的提交记录吧~
具体操作过程如下:
首先,找出大文件(在不知道文件名的情况下)。
找出排名前 5 的 pack 记录:
git verify-pack -v .git/objects/pack/pack-*.idx | sort -k 3 -g | tail -5
可以看到:
1753e0b6aa1cd3ed27d1d14e8e569664c685e896 blob 44600 43841 37970
ca12c545eae19d688ac840c7f0e2e623a1a4192b blob 45262 8534 140448
7a3265ee94c0ab25cf079ac8ccdf87f41d455d42 blob 54708 49093 171307
72590cee1315e32dada25535184dcee97c6f5af9 blob 1114323 1104823 113887612
4cc1f9dcef1004355d2a595d45808e99f100dc4d blob 114592569 113703558 184054
最后一条就是最大的一条记录,4cc1f9dcef1004355d2a595d45808e99f100dc4d 是它的 id。
找出该记录对应的文件:
git rev-list --objects --all | grep 4cc1f9dcef1004355d2a595d45808e99f100dc4d
可以看到:
4cc1f9dcef1004355d2a595d45808e99f100dc4d images/WechatIMG23.jpeg
如果知道文件路径,就直接执行下方移除操作,假设路径为:images/WechatIMG23.jpeg
将该文件从历史记录中移除:
git log --pretty=oneline --branches -- images/WechatIMG23.jpeg
重写所有 commit,将该文件从 Git 历史中完全移除:
git filter-branch --index-filter 'git rm --cached --ignore-unmatch images/WechatIMG23.jpeg' -- --all
到这里,历史记录中已经没有该文件了。不过运行 filter-branch 产生的日志还是会对该文件有引用,所以还需要运行以下几条命令,把该文件的引用完全删除:
rm -Rf .git/refs/original
rm -Rf .git/logs/
git gc
git prune
这时文件夹已经小多了。然后push代码,需强制 push:
git push --force
操作完毕。
其实filter-branch 的作用还不止这些,还可以用来修改历史提交记录中的用户名(username)和邮箱(email)等