Git删除大文件
我们在平时的项目开发中总是会忘记将不需要 Git 的文件或者文件夹添加进 .gitignore
中,一些不重要的小文件一般没有什么问题,但是如果不小心提交了大文件或者敏感信息,就会比较头疼。
之前我也写过一篇笔记:从Git历史中完全删除某个文件,就是因为我不小心将自己敏感配置信息通过 Git 上传到公开仓库中,需要从 Git 记录中删除信息,但是由于 Git 的特性,直接删除信息是没有用的,Git 会记录每次提交的所有信息,方便回滚。因此需要在 Git 中完全删除敏感信息操作。
这回也是同样的错误,我在本地开发项目,忘记将临时编译打包的大文件 /tmp/main.exe
添加进 .gitignore
中,最后导致把大文件通过 Git 提交到远程仓库中,并且导致 .git
文件很大。
实际上,通过 Git 提交大文件有几点不好的地方,一是提交了大文件会导致 .git
文件越来越大,之后 git clone
或者 git pull
的时候十分困难。二是 Git 会限制文件大小,一些很大的文件不能推送,可以使用 git lfs
,但是有免费容量限制。所以我一般会尽量避免大文件提交推送。
其实撤销大文件提交的原理,与从 Git 中删除文件的做法是差不多的,核心都是使用 git filter-branch
和 git gc
。
如果我们知道是哪一次 commit,提交推送了大文件,则可以撤销 commit 再重新提交。
列出提交记录
git log
依次撤销对应的提交记录
git reset 4ac0e5da919843axxxxxxxxxxxxxxxx
清理回收内存
rm -rf .git/refs/original/
git reflog expire --expire=now --all
git fsck --full --unreachable
git repack -A -d
git gc --aggressive --prune=now
重新提交推送
git add .
git commit -m "撤销大文件"
git push -f --all
如果是忘记了大文件是哪个 commit 提交推送的,或者是 commit 记录太久远了,则可以使用 git filter-branch
修改大文件记录。
列出记录中前 10 个最大的文件记录
git rev-list --all | xargs -rL1 git ls-tree -r --long | sort -uk3 | sort -rnk4 | head -10
100644 blob e0d29beda6fecbe332428481441a66c2fac9f99a 47987299 code/Gui/tmp/main.exe
100644 blob b9b43965e9a44acbe90e1ced9b1732a2fe350475 47810498 code/Gui/tmp/main.exe
100644 blob 62d000d6e12ab54dc6ab6e75b20a8ace1c79051e 3883008 code/fyne_demo.exe
100644 blob 8f8d6516a71151ae3afffe03be7a65c8a7f2c076 1072643 code/Gui/core/QRN
100644 blob 8f8d6516a71151ae3afffe03be7a65c8a7f2c076 1072643 code/Core/QRN
100644 blob 8f8d6516a71151ae3afffe03be7a65c8a7f2c076 1072643 code/App/core/QRN
比如这里我需要撤销 code/Gui/tmp/main.exe
这个大文件,使用 git filter-branch
命令。
git filter-branch --tree-filter "rm -f code/Gui/tmp/main.exe" -- --all
这样就会重写所有 code/Gui/tmp/main.exe
的记录,不过这时 .git
中空间还没有释放,需要清理回收内存。
rm -rf .git/refs/original/
git reflog expire --expire=now --all
git fsck --full --unreachable
git repack -A -d
git gc --aggressive --prune=now
最后再强制推送即可
git push -f --all