Git 2.51:MIDX 不再夹带 cruft,path walk 让 pack 更小
Git v2.51.0 于 2025 年 8 月发布,自 v2.50.1 以来共 506 个非 merge 提交,91 位贡献者。
参考材料:
- GitHub 博客亮点汇总:
- 官方发布说明 2.51.0:
无 cruft 的 multi-pack index
生成新 pack 时,Git 过去会排除任何已存在于不会被删除的 pack(含 cruft pack)中的对象。2.51 起改为额外保存那些唯一副本位于 cruft pack 中的对象及其祖先,从而保证非 cruft pack 的集合在可达性下是封闭的。
新增配置 repack.MIDXMustContainCruft,用于把 cruft pack 排除在 MIDX 之外。
git config repack.MIDXMustContainCruft true
git repack -ad
GitHub 在自家主力 monorepo 上的实测数据:MIDX 缩小约 38%,写入快 35%,读取性能提升约 5%。收益主要来自 MIDX 本身膨胀、cruft pack 又长期存在的仓库;如果仓库规模不大、cruft pack 几乎可以忽略,这项改动的实际体感有限。
用 path walk 换更小的 pack
新增了一种按 path 收集对象的 repack 方式(--path-walk API)。它不再按 revision 顺序遍历,而是把同一路径下的所有对象一起输出,绕开 name-hash 启发式,在同路径对象组内寻找 delta base。生成的 pack 往往明显更小,速度与既有的 revision order 大致相当。
git pack-objects --path-walk 同样会从同路径 blob 中找 delta base。
取舍上,适合开启的场景是:同一路径下堆积了大量历史对象(典型如长期演进的单个大文件),并且包体积是主要瓶颈。如果跨路径 delta 才是压缩收益的大头,path walk 能拿到的额外空间就比较有限;速度方面它只是与 revision order 持平,不会更快,代价是遍历方式变化后,原有的调参经验不一定直接套用。
stash 的交换格式
新增了一种 stash 内部表示的变体:把多个 stash 条目表示为一条 commit 序列——每个 stash 条目有 4 个 parent,多出的那个 parent 指向前一个 stash 条目。
这样整摞 stash 就能导出到单个 ref,像分支或 tag 一样 push / pull。对应的子命令是 git stash export 与 git stash import。
git log 的 changed-path Bloom filter
changed-path Bloom filter 现在支持多个字面量 pathspec,此前不能这样用:
git log -- path/to/a path/to/b
其他改动
git switch/git restore不再标记为实验性。git pull支持pull.autostash,可覆盖rebase.autostash/merge.autostash。git for-each-ref新增--start-after,便于分页。git cat-file --batch支持%(objectmode)原子,可区分缺失对象与子模块。- netrc 凭据助手支持文本服务名(如
smtp)。 gpg.program支持~展开。git add -p等交互命令遵循diff.context与-U。git pack-objects用--path-walk从同路径 blob 找 delta base。git push/git fetch批量更新 refs 提速。- 新增 R 语言 userdiff 模式。
面向 Git 3.0 的三件事
- reftable ref 后端已经足够成熟,Git 3.0 将把它作为新建仓库的默认格式。
- Git 3.0 将把默认哈希从 SHA-1 切换到 SHA-256。
git whatchanged计划弃用并移除,它的功能等价于git log --raw,需要的话提前把脚本里的调用换掉。