Git 仓库越拉越大:历史大文件、pack 膨胀与 gc 的正确姿势

举报
yd_291384559 发表于 2026/11/11 06:11:22 2026/11/11
【摘要】 Git 仓库体积暴涨多数不是工作区问题,而是历史大文件、残留对象和 pack 膨胀。本文给出定位大对象的命令、filter-repo 重写历史的步骤、gc/repack 的正确用法,以及 LFS 与 partial clone 等日常预防手段。

现象:工作区没多大,.git 却占了几个 G

接手老仓库时常见这种情况:du -sh . 只有几百 MB,du -sh .git 却是 3~5 GB,clone 一次要十几分钟。原因是 Git 保存的是快照与历史对象,删除文件并不等于删除历史。下面按「定位大对象 → 清理历史 → 压缩 pack → 日常预防」四步处理。

第一步:找出到底是谁占了空间

不要急着 git gc --aggressive,先定位。列出所有对象及其大小,按体积排序:

git rev-list --objects --all \
  | git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' \
  | awk '/^blob/ {print $3, $4}' | sort -nr | head -20

能直接看到「哪个历史版本里的哪个文件」最大。另一个视角是看 pack 内部:

git verify-pack -v .git/objects/pack/*.idx | sort -k3 -nr | head -10

第二步:清理历史大文件

如果确认是某个误提交的二进制(镜像、压缩包、数据库备份),普通 git rm 只能去掉最新版本的引用,旧 blob 仍留在历史里。需要重写历史,推荐 git filter-repo:

git filter-repo --path huge.iso --invert-paths

要点:执行前必须备份仓库;重写会改变所有相关 commit 的哈希,需要通知协作者重新 clone;随后强推 git push --force --all。团队共享仓库还要联系平台方清理服务器端缓存(例如合并请求产生的临时引用),否则对象可能被重新带回。

第三步:压缩 pack 与回收松散对象

先看现状:

git count-objects -vH

若 size-garbage 或 count 很大,说明有大量松散对象或残留包:

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

日常不要频繁使用 --aggressive,它耗时极长、收益有限;大仓库更适合用 git repack -Ad 重新打包。

第四步:从源头预防

  • 二进制文件交给 Git LFS,仓库只保留指针;
  • 补全 .gitignore,构建产物、日志、数据集不要入库;
  • 提交前用 git diff --cached --stat 看一眼体积;
  • 只读拉取用 partial clone:git clone --filter=blob:none,按需下载 blob,CI 里能省下大量时间;
  • 定期在 CI 中跑 git count-objects -vH 做体积巡检。

小结

仓库膨胀基本逃不出三类原因:历史大文件、松散对象与 pack 膨胀、二进制误入库。先用命令量出体积,再决定重写历史还是 gc,比盲目执行 gc 有效得多;重写历史是不可逆操作,务必先备份并同步团队。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。