Git 永久移除历史记录中的大文件
问题场景
在使用Git进行版本控制时,可能会遇到误将体积较大的文件提交到仓库的情况。即使后续删除了该文件,其历史记录仍然占据着仓库空间,导致克隆、推送和拉取操作变得缓慢。
解决方案
本文介绍一种彻底从Git历史记录中移除大文件的方法。
步骤一:准备工作
首先确保工作区处于干净状态,可以执行commit、stash或checkout操作。
步骤二:执行垃圾回收
git gc
此操作会对仓库中的对象进行压缩整理。
步骤三:检查仓库空间使用情况
git count-objects -v
执行后可以观察到size-pack字段,该数值表示packfiles的大小(单位为KB)。
步骤四:识别大型对象
使用底层命令git verify-pack来定位占用空间较大的对象,并对文件大小进行排序:
git verify-pack -v .git/objects/pack/pack-*.idx | sort -k 3 -n | tail -5
输出结果的第三列为文件大小(字节)。
步骤五:查找对象对应的文件名
获取目标对象的SHA值后,使用以下命令查看其对应的文件路径:
git rev-list --objects --all | grep {blob_sha}
步骤六:确认问题文件的提交历史
git log --pretty=oneline --branches -- {目标文件路径}
步骤七:从历史记录中移除文件
使用filter-branch命令重写包含该文件的所有提交:
git filter-branch --index-filter 'git rm --cached --ignore-unmatch {目标文件路径}' -- {起始提交哈希}..HEAD
参数说明:
--index-filter:修改索引而非磁盘上的文件,执行速度更快git rm --cached:从索引中移除文件,保留工作区的文件--ignore-unmatch:当文件不存在时避免报错{起始提交哈希}:问题文件首次提交的哈希值,从该提交开始重写历史
步骤八:清理残留引用
执行完上一步后,历史记录中已无该文件的引用,但reflog和.git/refs/original目录中仍有残留,需要清理:
rm -rf .git/refs/original
rm -rf .git/logs/
git gc --prune=now --aggressive
注意:此操作会清除本地仓库的操作历史,请确认完成后再执行。
步骤九:验证空间释放效果
git count-objects -v
对比操作前后的size-pack数值,确认空间已释放。
步骤十:推送更新
完成上述操作后,可将清理后的分支推送到远程仓库:
git push --force origin {分支名}
补充:彻底删除对象
如需完全移除对象(不再保留引用),可执行:
git prune