bigywater.tech
Git · 24

gc.auto 阈值:松散对象多到多少才自动 gc

松散对象多到多少才会自动 gc?文档说 6700,但 git 并不真的数 6700 个。这篇用精确构造的 26、27、28 个对象和随机分布的几千个对象,把触发点测出来,再看 gc 之后还会不会再触发,以及 pack 数量这个另一条触发条件。

28
objects/17 里松散对象达到 28 个(超过 27)才触发 git gc --auto
6,700 不触发
随机分布的 6,700 个松散对象,objects/17 里只有 17 个,没有触发;6,500 个反而触发了
51
pack 数超过 gc.autoPackLimit(50)也会触发,打包后合并成 1 个

怎么数

实测 · 本机执行输出
  $ git config --get gc.auto || echo "gc.auto 未设置(git 默认 6700)"
  gc.auto 未设置(git 默认 6700)
  (6700 + 255) // 256 = 27:objects/17 里松散对象超过 27 个才触发

git gc --auto 不去数全部松散对象——那太贵。它只数 .git/objects/17 一个目录里的文件,和 (gc.auto + 255) / 256 比较,默认 gc.auto 是 6700,阈值 27,超过才触发。因为对象 hash 均匀分布,一个目录约占 1/256。

精确的边界

实测 · 本机执行输出
  objects/17 里 26 个 → git gc --auto 输出: (没有输出,什么也没做)
  objects/17 里 27 个 → git gc --auto 输出: (没有输出,什么也没做)
  objects/17 里 28 个 → git gc --auto 输出: Auto packing the repository for optimum performance. / See "git help gc" for manual housekeeping. / warning: There are too many unreachable loose objects; run 'git prune' to remove them.

人为往 objects/17 里放 26、27、28 个对象:27 个仍不触发,28 个触发。这证实了是“超过 27”。

估计有误差

实测 · 本机执行输出
      松散对象总数   objects/17 个数  触发 gc --auto
       5,000              14  否
       6,000              27  否
       6,500              33  是
       6,700              17  否
       7,000              32  是
       7,500              35  是
       8,000              29  是

随机分布的对象让 objects/17 的个数上下波动:6,000 个对象时 27 个(没触发),6,700 个时只有 17 个(没触发),6,500 个时 33 个(触发)。所以“松散对象 6700 个触发”只是个大概的数。

触发之后

实测 · 本机执行输出
  第一次触发之后 objects/17 里还有 28 个松散对象
  第 1 次再执行 git gc --auto:
    Auto packing the repository for optimum performance.
    See "git help gc" for manual housekeeping.
    Nothing new to pack.
    warning: There are too many unreachable loose objects; run 'git prune' to remove them.
  第 2 次再执行 git gc --auto:
    Auto packing the repository for optimum performance.
    See "git help gc" for manual housekeeping.
    Nothing new to pack.
    warning: There are too many unreachable loose objects; run 'git prune' to remove them.
  两次之后 objects/17 里仍有 28 个

自动 gc 会打包可达对象,但不可达的松散对象不满过期时间是不会被清理的,于是 objects/17 里的数量不变,下一次 gc --auto 又会触发并警告 too many unreachable loose objects。要清理它们得 git prune 或等它们过期。

pack 数

实测 · 本机执行输出
  现在有 50 个 pack
  git gc --auto → (没有输出);pack 数 50
  再多一个:51 个 pack
  git gc --auto → Auto packing the repository for optimum performance. / See "git help gc" for manual housekeeping.;pack 数 1

另一个条件是 pack 数量:超过 gc.autoPackLimit(默认 50)就会触发,把它们合并成一个。

分步演示

gc.auto 阈值
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / git 2.54.0(Apple Git-157);每个实验在临时目录里新建仓库,HOME 和全局配置指向实验专用的空目录(不读用户自己的 git 配置),提交的作者与时间固定以便复现;需要网络协议的实验用本机的 file:// 或 git daemon 回环端口(9800 以上),不碰任何远程仓库;计时用 time.perf_counter,数字每次运行会有小幅抖动。这一篇的实验用一份不含 gc.auto 与 maintenance.auto 的全局配置,以便用 git 的默认值;为了观察输出,gc --auto 以 -c gc.autoDetach=false 同步运行;松散对象用 git hash-object -w --stdin-paths 写入(不可达);“objects/17 里 28 个”是用 SHA-1 前缀为 17 的内容构造的
    • 没有验证:默认 autoDetach 时在后台运行及 gc.log 的写入与 1 天内不再重试的行为;gc.auto 设为其它值时阈值的变化(只验证了默认值);git commit 之后触发 maintenance run --auto 的完整流程(见后面 maintenance 一篇);gc.autoPackLimit 设为其它值;Windows 上的行为
    京ICP备2026067502号-1京公网安备11010502063487号