怎么解决 Git 协作中大文件提交导致仓库体积过大

文章导读
如果大文件已经提交进历史,单纯清理缓存无效,必须重写历史;如果是新文件,直接用 Git LFS 托管。
📋 目录
  1. A 安全须知:操作前必读
  2. B 环境准备
  3. C 命令速用版
  4. D 分步处理
  5. E 怎么验证是否生效
  6. F 常见坑
  7. G 参考来源
A A

如果大文件已经提交进历史,单纯清理缓存无效,必须重写历史;如果是新文件,直接用 Git LFS 托管。

先说结论:历史里的大文件必须通过重写提交记录彻底移除,配合垃圾回收才能释放空间,后续大文件应改用 Git LFS 管理。

  • 先定位:用 rev-list 扫描占用空间最大的对象及其路径
  • 先做:用 filter-repo 重写历史移除文件,再强制清理 reflog 和 gc
  • 再验证:检查本地 .git 体积和远程仓库配额,确认旧提交不可访问

安全须知:操作前必读

重写历史是高风险操作,会导致提交哈希值改变。在执行任何清理命令前,请务必完成以下准备:

  • 全量备份:克隆一份完整的仓库副本到本地其他目录,以防操作失误无法恢复。
  • 团队通知:强制推送会破坏协作者的本地历史,必须通知所有成员重新克隆或重置分支。
  • 确认权限:确保你有权限强制推送(force push)到远程仓库。

环境准备

git-filter-repo 不是 Git 自带命令,需要单独安装。推荐使用 pip 安装:

pip install git-filter-repo

安装完成后,验证是否可用:

git filter-repo `--version`

命令速用版

扫描最大的 20 个文件对象:

git rev-list `--objects` `--all` | git cat-file `--batch-check`='%(objecttype) %(objectname) %(objectsize) %(rest)' | awk '/^blob/ {print substr($0,6)}' | sort `--numeric-sort` `--key`=2 | tail -20

清理垃圾并立即回收:

git reflog expire `--expire`=now `--all`
git gc `--prune`=now `--aggressive`

分步处理

1. 定位大文件
使用上述扫描命令找出占用空间大的文件路径和 SHA。如果已知报错信息中有哈希值,可用 git rev-list `--objects` `--all` | grep <哈希> 反查路径。

怎么解决 Git 协作中大文件提交导致仓库体积过大

2. 重写历史移除文件
不要用已弃用的 git filter-branch,推荐使用 git filter-repo。例如移除 dist.zip:

git filter-repo `--path` dist.zip `--invert-paths` `--force`

如果是 Gitee 用户,也可使用其自研工具 git-repo-clean 进入交互式界面处理。

3. 清理引用并垃圾回收
重写后旧对象仍可能被 reflog 引用,必须执行:

git reflog expire `--expire`=now `--all`
git gc `--prune`=now `--aggressive`

4. 强制推送到远程
历史已改变,需强制推送。注意这会影响协作者,需提前通知:

git push `--force`

5. 预防再次发生
安装 Git LFS,跟踪大文件类型,避免再次直接提交二进制大文件:

git lfs install
git lfs track "*.h5"
git add .gitattributes

怎么验证是否生效

本地执行 git count-objects -vH 查看体积,对比处理前后的 pack 文件大小。远程仓库可在网页端查看仓库大小配额使用情况。若远程仍显示过大,可能是平台保留了旧引用(如 GitHub 默认保留 30 天),需等待或联系平台清理。

常见坑

  • git gc 无效:没先让对象不可达就直接跑 gc,体积不会变。必须先删分支、重写历史或清空 reflog。
  • 远程未同步:本地变小但远程没变,是因为远程有保留策略。别人 fetch 过的旧提交也可能导致远程无法立即丢弃对象。
  • 协作冲突:重写历史会改变提交 SHA,协作者必须重新克隆或重置本地分支,否则推送会冲突。
  • 工具选择:git filter-branch 慢且易出错,官方已不推荐。优先选 git filter-repo 或 BFG Repo-Cleaner。

参考来源

  • git-filter-repo 官方文档:https://html.github.io/git-filter-repo/
  • Git LFS 官方介绍:https://git-lfs.com/
  • Git gc 文档:https://git-scm.com/docs/git-gc