推荐使用 git filter-repo 或 BFG Repo-Cleaner 重写提交历史来移除大文件,操作前必须备份仓库并通知所有协作者。此操作会改写提交哈希,导致原有克隆失效,仅建议在仓库早期或必要时进行。
先说结论:清理 Git 历史大文件的核心是重写提交历史,必须使用过滤工具配合垃圾回收,且需团队协同。
- 先定位:使用
git rev-list或git-scan-tree找出占用空间最大的文件路径。 - 先做:本地执行过滤命令清理历史,确认无误后再强制推送到远程。
- 再验证:推送后检查远程仓库大小,并通知团队成员重新克隆。
命令速用版
以下命令用于检查仓库大小及移除大于指定体积的文件,需在本地仓库根目录执行。
# 查看仓库对象大小分布
git count-objects -vH
# 使用 git-filter-repo 移除大于 10M 的文件
git filter-repo `--strip-blobs-bigger-than` 10M
# 清理无用对象并压缩
git reflog expire `--expire`=now `--all`
git gc `--prune`=now `--aggressive`为什么会这样
Git 默认保留所有历史对象的完整快照,删除文件不会立即释放空间。
Git 存储的是快照而非差异,即使你在某次提交中删除了大文件,该文件依然存在于之前的提交对象中。普通的 git gc 只能清理未被引用的对象,无法移除历史提交中已引用的大文件,必须重写历史才能彻底清除。
分步处理
按顺序执行以下步骤,每步完成后确认无误再进行下一步。
1. 备份仓库
克隆一份完整备份到本地其他目录,防止操作失误导致数据丢失。
git clone `--mirror` <repository-url> backup-repo.git2. 安装过滤工具
推荐使用 git-filter-repo,比传统的 git filter-branch 更快更安全。
pip install git-filter-repo3. 分析大文件
找出具体是哪个文件或路径占用了空间,避免误删。
git rev-list `--objects` `--all` | git-cat-file `--batch-check`='%(objecttype) %(objectname) %(objectsize) %(rest)' | sed -n 's/^blob //p' | sort -r `--numeric-sort` -k2 | head -n 104. 执行清理
根据分析结果,按路径或大小过滤。清理后必须立即执行垃圾回收。
git filter-repo `--strip-blobs-bigger-than` 10M
git reflog expire `--expire`=now `--all`
git gc `--prune`=now `--aggressive`5. 强制推送
历史已改写,必须强制推送覆盖远程仓库,此操作会影响所有协作者。
git push `--force` `--all`
git push `--force` `--tags`怎么验证是否生效
通过本地对象统计和远程仓库页面显示确认体积变化。
本地验证:再次运行 git count-objects -vH,观察 size-pack 是否明显减小。
远程验证:刷新 GitHub 或 GitLab 仓库设置页面的 Size 显示,公开资料中没有看到可靠的量化数据,具体减少比例取决于大文件在历史中的占比。
全新克隆:在临时目录重新克隆仓库,检查下载体积是否符合预期。
常见坑
- 保护分支限制:远程仓库若开启分支保护,可能拒绝强制推送,需临时关闭保护策略。
- CI/CD 缓存:流水线缓存可能仍保留旧对象,需手动清除构建缓存。
- 协作者同步:其他成员必须重新克隆或执行复杂的重置操作,否则推送会被拒绝。
- 工具选择:避免使用
git filter-branch,官方文档已建议其用于遗留场景,效率较低且易出错。
常见问题
git gc 能直接清理历史大文件吗?
不能,git gc 只能清理未被引用的对象,无法移除历史提交中已引用的大文件。
清理后原来的提交记录还在吗?
不在,重写历史会生成新的提交哈希,原有提交记录会被替换。
只删除最近一次提交的大文件怎么做?
使用 git reset `--hard` HEAD~1 回退版本,或 git commit `--amend` 修改最近提交。
参考来源
- Git Documentation: git-filter-repo - https://git-scm.com/docs/git-filter-repo
- GitHub Docs: Removing sensitive data from a repository - https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/removing-sensitive-data-from-a-repository
- Atlassian Git Tutorial: git push - https://www.atlassian.com/git/tutorials/syncing/git-push