大数跨境

Git 2.56|版本更新一览及新特性全景

Git 2.56|版本更新一览及新特性全景 苏哲管理咨询
2026-10-22
4
导读:Git 2.56 由 104 位贡献者开发,新增git add --resolved,可安全暂存已解决冲突,避免误提交无关修改。优化 merge-base 历史遍历算法,大型单体仓库可提速数十倍。Pa

开源 Git 项目刚刚发布 Git 2.56。下面是 GitHub 整理的本次版本中一些最值得关注的新特性与变更。

 作者:Elijah Newren 发布时间:2026-09-28 

开源 Git 项目正式发布 Git 2.56.0,本次版本合并了来自 104 位贡献者的功能与 bug 修复,其中 39 位是首次贡献。上一期版本解读我们介绍了 Git 2.55。 借此新版本发布,下面为大家解读本次版本的重点更新。

暂存已解决冲突,而不把其他改动一并提交

解决合并冲突分为两个步骤:

  1. 在工作区编辑冲突文件,得到你想要的合并结果;
  2. 将这些文件暂存,告诉 Git 冲突已经解决。

假设合并时 recipe.txt出现冲突,而 notes.txt存在无关的本地修改。

第二步听起来简单,但原有命令很容易误暂存你并不想提交的内容。git add -u会更新所有已跟踪且被修改的文件。在合并过程中,它会包含和冲突无关的本地改动;如果你遗漏了某个冲突标记,甚至会把仍带有冲突标记的文件暂存进去。

Git 2.56 提供更安全的工作流:

$ git add --resolved
fatal: the following paths still have conflict markers:
        recipe.txt
# 编辑 recipe.txt,删除冲突标记
$ git add --resolved
$ git status --short
 M notes.txt
M  recipe.txt

新增的 git add --resolved专门用于这个场景:仅处理索引中处于未合并状态的文件。在执行暂存前,它会扫描未合并普通文件,检查是否残留冲突标记。一旦发现,直接列出文件路径,不修改索引。

git status --short的两列可以区分已暂存和未暂存改动:recipe.txt被标记为已暂存、冲突已解决;而 notes.txt的无关修改仍然保持未暂存。

你也可以传入路径限定只处理部分未合并文件。检查规则仍是全有或全无:选中的普通文件里只要任意一个还带有冲突标记,所有文件都不会被暂存。已解决的删除冲突、二进制文件冲突没有文本冲突标记,可以正常暂存。

这个命令的作用范围比 git add -u/ git add -A更小。--resolved不能和这两个模式混用,并且会忽略从未发生冲突的已跟踪文件。对于合并前本地就存在无关修改的维护者工作流,它是一道很好的安全屏障。

找不到更多合并基节点时,提前终止历史遍历

很多 Git 操作需要找到两个提交之间最佳公共祖先(合并基):合并操作以合并基作为变更合并起点;三点式 diff 依靠合并基确定主题分支的起始提交;代码托管平台也依靠这个计算 PR diff、可合并性检查、评审范围等对比。

Git 的查找方式是从两个提交节点同时向后遍历历史。可以理解为:把一侧可达提交标蓝色,另一侧标红色;同时被两种颜色覆盖的提交,就是合并基候选。

只找到一个候选并不够。交叉合并会产生多个合并基,它们互相之间不存在祖先关系,Git 必须持续遍历直到确认找到全部合并基。旧版终止规则存在问题:找到合并基之后,还会继续遍历一长串已经属于共同历史的陈旧提交。

Git 2.56 新增统计逻辑,跟踪两侧还剩下多少仅属于单方的待遍历提交。简单来说:当其中一侧独有的提交遍历完毕后,不可能再出现新的公共节点,Git 可以直接停止遍历,同时保证返回全部合并基。

在大型仓库场景提升非常显著。在一个真实单体仓库案例中,遍历耗时从 0.68s 降至 0.01s。两个大型单体仓库的生产测试:一个场景提速约 70 倍,另一个平均提速约 20 倍。

该系列提交也修复了 Linux 内核一个长期存在的性能问题。在 Git 默认 v2 提交图下,git merge-base --all v4.8 v4.9的遍历步数从 167441 步、0.29 秒,降到 3887 步、0.01 秒。

让服务端可以落地更小的路径遍历打包(path-walk repack)

Git 打包仓库时,会寻找相似对象,以增量(delta)方式压缩存储。传统方式使用名称哈希分组候选对象。 路径遍历打包(path-walk repack)则按照文件树位置遍历对象,把同一路径的多个版本放到一起,更容易找到更优的增量关系,节省大量存储空间。

基准测试:克隆微软 FluentUI 仓库,强制重新计算增量。普通位图打包得到 558.5MB pack 文件;使用 --path-walk打包仅 164.4MB,体积减少约 71%。

但代码托管平台不只关心包体积:它们普遍使用可达性位图快速查询对象集合,部分平台还使用 delta islands(增量隔离岛),防止一组引用内的对象依赖另一组引用中的对象。过去 path-walk repack 和这两项特性不兼容,限制了它在生产环境落地。

Git 2.56 解除了这两个限制:

  1. path-walk 打包现在可以为新打包文件生成位图;后续 git pack-objects会优先复用已有位图,仅必要时才启用路径遍历;
  2. path-walk 现在支持 delta islands 的记账逻辑:在选择增量基之前,把岛归属信息沿着提交和树向下传播。

平台可以保留对象隔离规则,同时体验 path-walk 带来的存储缩减。

注意:本次更新不会默认开启 path-walk repack,只是移除两大落地障碍,方便大型代码托管平台评估存储收益。

冰山一角:其他重要更新

上面只是 Git 2.56 的部分变更,还有不少值得关注的新特性:

  1. 实验性命令 git history 继续增强
    Git 2.54 引入该命令,支持 reword、split;2.55 增加 fixup;2.56 新增:
git history drop <commit>

该命令删除指定提交,并把后续提交重放至被删提交的父节点。如果 HEAD 发生移动,Git 更新索引和工作区,保留无关本地修改;重放冲突或会覆盖本地修改时直接中止。该命令仍处于实验阶段,不能处理包含合并提交的历史,也不能删除根提交、合并提交。

  1. 底层引用操作统一到 git refs 工具箱
    过去修改引用的底层命令分散在 git update-ref、git symbolic-ref等多个底层工具。Git 2.56 将底层引用管理收敛到 git refs:
git refs create refs/heads/topic <new-value>
git refs update refs/heads/topic <new-value> [<old-value>]
git refs delete refs/heads/topic [<old-value>]
git refs rename refs/heads/old refs/heads/new

可选旧值参数提供 CAS(比较并交换)保护,保证更新、删除的原子性。 这是底层命令:git refs rename只会移动引用和 reflog,不会像 git branch -m 那样调整分支配置。

  1. 批量删除已合并本地分支
    上游分支合入后清理本地主题分支,新增批量操作:
git branch --delete-merged 'origin/*' 'topic-*' --dry-run
  • origin/*
    :匹配上游在 origin 的分支;
  • topic-*
    :限定本地分支名以 topic - 开头;
  • --dry-run
    :预览待删除分支,不会真实删除。

去掉 --dry-run后,Git 只会删除分支尖端可被上游分支访问的本地分支。会跳过当前工作区检出的分支、上游缺失的分支、存在模糊推送配置的分支。 配置 branch.<name>.deleteMerged = false可以保护分支,避免被批量清理。

  1. git bisect run 新增 --reset-when-foundgit bisect run
    用来定位引入缺陷的提交,但查找结束后默认停留在坏提交,需要手动执行 git bisect reset。 新增选项 --reset-when-found[=<where>]合并两步操作:
  • 默认 original:回到二分查找开始前检出的提交;
  • found
    清理二分状态,但停留在找到的问题提交。 该选项不能和 --no-checkout一起使用。
  1. git replay 新增 --linearize,扁平化合并拓扑
    实验命令 git replay现在支持 --linearize,可以把历史展开成单线、丢弃合并提交,效果等价 git rebase --no-rebase-merges,但全程不操作工作区。该参数不能和 --contained或多分支同时回放混用。
  2. 命令行拼写纠错提示
    Git 现在识别两类常见命令笔误,并给出推荐写法:
  • 输入 git push origin/main,提示改为 git push origin main
  • 输入 git branch --set-upstream-to origin main,提示改为 git branch --set-upstream-to=origin/mainGit 会先校验修正是否合理,不会无差别猜测。
  1. 部分克隆:可手动丢弃按需拉取的大 Blob
    部分克隆初始不会下载全部对象,按需获取的 Blob 下载后会永久保存在本地。Git 2.56 支持丢弃可重新获取的大 Blob,依赖远程 promisor 按需再次拉取:
# 预览
git repack -a --filter=blob:limit=1m --drop-filtered --dry-run
# 执行清理
git repack -a --filter=blob:limit=1m --drop-filtered

dry-run 列出候选文件;正式命令会在本地删除这些 Blob,后续访问时重新从远端拉取。 这是手动清理机制,不是自动缓存回收,目前仅支持 blob:limit 过滤器。需要配置 promisor 远程;如果对象被当前索引引用,Git 会拒绝删除。本功能是 GSoC 项目成果。

  1. git log --follow 在非线性历史下追踪文件改名更可靠
    旧版逻辑只维护一个全局 “当前路径”;如果不同父分支对同一个文件做不同重命名,遍历顺序会影响最终追踪结果。Git 2.56 为每个父节点单独记录路径,结果不再受遍历顺序影响,修复子树合并等场景下的文件改名追踪问题。
  2. git log --graph 多根提交图渲染优化
    存在多个根提交的历史图中,无关提交会直接画在根提交下方同一列,看起来像存在关联。Git 2.56 默认对这类 “视觉根节点” 增加缩进:
  * root of one visible history
  * unrelated commit

默认开启;--no-graph-indent切回旧渲染逻辑,也可以配置 log.graphIndent修改默认行为。

  1. 大量底层性能优化,消除性能断崖
    多项内部改动解决大规模仓库的性能拐点:
  • reftable 写锁后避免冗余重载,文件 stat 调用由随引用数量线性增长变为常量复杂度;
  • 加载新 pack 文件不再每次扫描全量列表,消除 O (N²) 性能退化;
  • 针对大量墓碑记录的 reftable、路径限定工作区 diff 移除平方级扫描;未跟踪文件收集稳定为 O (n log n);

效果示例:

  • reftable 墓碑性能测试:13s → 0.2s;
  • Chromium 仓库(约 50 万索引条目)的某条 git diff:8 分钟 → 0.07 秒。

以上只是本次版本变更的一部分。完整更新日志可以查看官方 RelNotes:https://github.com/git/git/blob/v2.56.0/Documentation/RelNotes/2.56.0.adoc

要点总结

  1. ✅ git add --resolved:合并冲突专用暂存,自动校验冲突标记,不碰无关本地修改,提升合并安全。
  2. ✅ merge-base 算法提速:遍历提前终止,超大型 monorepo 数十倍提速,Linux 内核历史查询性能大幅改善。
  3. ✅ Path-walk repack 支持位图与 delta islands,服务端可启用,仓库体积最高可降 70%+。
  4. ✅ 实验命令增强:git history drop删除提交;git replay --linearize扁平化历史,不操作工作区。
  5. ✅ 新底层命令 git refs,统一引用操作。
  6. ✅ git branch --delete-merged批量清理已合并本地分支。
  7. ✅ git bisect run --reset-when-found自动回退检出状态。
  8. ✅ 部分克隆支持手动清理大 Blob,按需重拉。
  9. ✅ log 图形渲染、文件改名追踪逻辑优化。
  10. ✅ 大量底层性能优化,修复 O (N²) 瓶颈,超大仓库 diff、reftable 读写巨大提速。

【声明】内容源于网络
0
0
苏哲管理咨询
为企业及组织提供AI+战略、数智化转型咨询及观点、建议等
内容 2381
粉丝 0
苏哲管理咨询 为企业及组织提供AI+战略、数智化转型咨询及观点、建议等
总阅读68.1k
粉丝0
内容2.4k