土法炼钢兴趣小组的算法知识备份

【Git 内部】gc、repack 与 prune

文章导航

分类入口
opensource
标签入口
#git#git-internals#git-gc#repack#prune#count-objects

目录

仓库用久了,松散对象堆积、info/packs 过时、reflog 过长——git gc(garbage collect)是 Git 自带的磁盘整理入口。它不等于「删除历史」,而是 repack 对象、修剪过期 reflog、可选 prune 不可达松散对象。搞清 gc 改写了哪些路径,才能解释「gc 后仓库变小」或「gc 跑很久」。


一、git gc 做什么

默认 git gc 大致包括(版本与配置略有差异):

  1. repack:把松散对象打入 pack(git repack -d -l 一类组合)。
  2. prune:删除已被 pack 收录且可安全删除的松散对象;--prune=now 立即执行而非延迟。
  3. reflog 过期:删除超过 gc.reflogExpire 的条目。
  4. 松散不可达对象:prune 悬空对象(无 ref/reflog 指向)。
  5. 更新 objects/info/packs、可能写 bitmap / commit-graph(配置开启时)。
git gc 主路径:repack、更新 packs 清单、prune、修剪 reflog

记录文件:.git/gc.log(若存在)记载上次 gc 时间。


二、count-objects 字段

git count-objects -v

实测(repack 后、gc 前,Git 2.54.0):

count: 0
size: 0
in-pack: 3
packs: 1
size-pack: 1
prune-packable: 0
garbage: 0
size-garbage: 0
字段 含义
count / size 松散对象个数与 KB
in-pack / size-pack pack 内对象数与 pack 体积
packs pack 文件个数
prune-packable 已在 pack 中、可 prune 的松散对象数
garbage 损坏或异常对象
git count-objects -v 各字段在 repack 后的典型值

git gc --prune=now 后松散 objects/xx/ 通常清空,仅留 objects/pack/objects/info/


三、info/packs

objects/info/packs 列出本仓库使用的 pack 及顺序,例如:

P pack-8f8a6ea89a77b5e25da24dc54481874c20bbcc7a.pack

读取对象时 Git 按此清单定位 pack。repack 合并多个 pack 为一个后,此文件被重写。


四、何时需要手动 gc

注意:gc 会占用 CPU 与 IO;大仓库应在低峰跑。git repack -Ad 比默认 gc 更激进(单 pack),耗时更长。


五、与可达性

prune 删除的是不可达对象:无 ref、无 reflog、无 stash 等引用能 walk 到的 commit/tree/blob。仍被 reflog 指向的「孤立」提交在 reflog 过期前不会被 prune——见 reflogfsck


六、本文边界

复现:

git count-objects -v
git gc --prune=now
find .git/objects -type f | sort

参考资料

系列索引Git 内部结构 · 上篇commit-graph · 下篇fsck

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。


By .