跳转到内容

垃圾回收 (GC)

随着时间的推移,你的 Git 仓库会积累大量的“松散对象”(loose objects)。这些可能是被废弃的提交、过期的索引快照或者是为了效率而尚未打包的文件。如果不加维护,.git 目录会变得臃肿,操作速度变慢。

git gc (Garbage Collection) 就是 Git 的清洁工。

Git 存储数据有两种方式:

  1. 松散对象 (Loose Objects):每个文件、提交、树对象都单独存储为一个文件(在 .git/objects/xx/ 下)。写入快,但占用大量 inode 和磁盘空间。
  2. 打包文件 (Packfiles):为了节省空间,Git 会将多个对象压缩到一个二进制包文件中(.pack),并创建一个索引文件(.idx)来快速查找。

git gc 的主要任务就是将松散对象压缩成 Packfiles,并清理那些不再被引用的“悬空对象”(dangling objects)。

通常情况下,你不需要手动运行它。Git 在执行部分命令(如 git pushgit merge)后可能触发 git gc --auto,具体取决于配置和松散对象数量是否超过阈值(默认约 6700 个)。

但在以下情况,你可能需要手动介入:

  • 刚刚进行了大量的历史重写(rebase, filter-branch)。
  • 仓库体积异常大,git clone 很慢。
  • 感觉到本地操作(如 git status)有明显的延迟。
Terminal window
# 标准清理
git gc
# 强力清理(更激进,耗时更长)
git gc --aggressive

--aggressive 参数会让 Git 使用更深的 delta 压缩窗口(从默认的 10 增加到 250),花更多时间来寻找最优的压缩差异,通常能进一步减小仓库体积。但需注意,这主要是用时间换空间,对于已经优化过的仓库收益有限,一般不建议频繁使用。

在运行 GC 之前或之后,你可能想知道仓库的健康状况。

Terminal window
git count-objects -vH
  • -v: 详细输出 (verbose)
  • -H: 人类可读格式 (human-readable)

输出示例:

count: 10 <-- 松散对象数量
size: 40.00 KiB <-- 松散对象占用空间
in-pack: 523 <-- 已打包对象数量
packs: 1 <-- 包文件数量
size-pack: 1.20 MiB
prune-packable: 0
garbage: 0
size-garbage: 0 bytes

如果 count 很大(成千上万),说明你需要运行 git gc 了。

默认情况下,git gc 只会清理两周前(默认配置)的悬空对象,以防你误删了还有用的数据。实际的可恢复窗口受 gc.pruneExpire(默认 2 周)与 reflog 过期策略(gc.reflogExpire 默认 90 天)共同影响。

如果你确定要立即彻底清理所有不可达的对象(例如在敏感数据清除操作后):

Terminal window
# 立即修剪所有不可达对象
git gc --prune=now

保持仓库整洁是系统管理员的基本素养。定期检查 git count-objects 并在必要时手动运行 git gc,可以让你的 Git 仓库始终保持飞一般的速度。