开源 Git 项目刚刚发布 Git 2.56。下面是 GitHub 整理的本次版本中一些最值得关注的新特性与变更。
作者:Elijah Newren 发布时间:2026-09-28
开源 Git 项目正式发布 Git 2.56.0,本次版本合并了来自 104 位贡献者的功能与 bug 修复,其中 39 位是首次贡献。上一期版本解读我们介绍了 Git 2.55。 借此新版本发布,下面为大家解读本次版本的重点更新。
暂存已解决冲突,而不把其他改动一并提交
解决合并冲突分为两个步骤:
-
在工作区编辑冲突文件,得到你想要的合并结果; -
将这些文件暂存,告诉 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 解除了这两个限制:
-
path-walk 打包现在可以为新打包文件生成位图;后续 git pack-objects会优先复用已有位图,仅必要时才启用路径遍历; -
path-walk 现在支持 delta islands 的记账逻辑:在选择增量基之前,把岛归属信息沿着提交和树向下传播。
平台可以保留对象隔离规则,同时体验 path-walk 带来的存储缩减。
注意:本次更新不会默认开启 path-walk repack,只是移除两大落地障碍,方便大型代码托管平台评估存储收益。
冰山一角:其他重要更新
上面只是 Git 2.56 的部分变更,还有不少值得关注的新特性:
- 实验性命令 git history 继续增强
Git 2.54 引入该命令,支持 reword、split;2.55 增加 fixup;2.56 新增:
git history drop <commit>
该命令删除指定提交,并把后续提交重放至被删提交的父节点。如果 HEAD 发生移动,Git 更新索引和工作区,保留无关本地修改;重放冲突或会覆盖本地修改时直接中止。该命令仍处于实验阶段,不能处理包含合并提交的历史,也不能删除根提交、合并提交。
- 底层引用操作统一到 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 那样调整分支配置。
- 批量删除已合并本地分支
上游分支合入后清理本地主题分支,新增批量操作:
git branch --delete-merged 'origin/*' 'topic-*' --dry-run
origin/*:匹配上游在 origin 的分支; topic-*:限定本地分支名以 topic - 开头; --dry-run:预览待删除分支,不会真实删除。
去掉 --dry-run后,Git 只会删除分支尖端可被上游分支访问的本地分支。会跳过当前工作区检出的分支、上游缺失的分支、存在模糊推送配置的分支。 配置 branch.<name>.deleteMerged = false可以保护分支,避免被批量清理。
- git bisect run 新增 --reset-when-found
git bisect run用来定位引入缺陷的提交,但查找结束后默认停留在坏提交,需要手动执行 git bisect reset。 新增选项--reset-when-found[=<where>]合并两步操作:
-
默认 original:回到二分查找开始前检出的提交; found清理二分状态,但停留在找到的问题提交。 该选项不能和 --no-checkout一起使用。
- git replay 新增 --linearize,扁平化合并拓扑
实验命令 git replay现在支持--linearize,可以把历史展开成单线、丢弃合并提交,效果等价git rebase --no-rebase-merges,但全程不操作工作区。该参数不能和--contained或多分支同时回放混用。 - 命令行拼写纠错提示
Git 现在识别两类常见命令笔误,并给出推荐写法:
-
输入 git push origin/main,提示改为git push origin main -
输入 git branch --set-upstream-to origin main,提示改为git branch --set-upstream-to=origin/mainGit 会先校验修正是否合理,不会无差别猜测。
- 部分克隆:可手动丢弃按需拉取的大 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 项目成果。
- git log --follow 在非线性历史下追踪文件改名更可靠
旧版逻辑只维护一个全局 “当前路径”;如果不同父分支对同一个文件做不同重命名,遍历顺序会影响最终追踪结果。Git 2.56 为每个父节点单独记录路径,结果不再受遍历顺序影响,修复子树合并等场景下的文件改名追踪问题。 - git log --graph 多根提交图渲染优化
存在多个根提交的历史图中,无关提交会直接画在根提交下方同一列,看起来像存在关联。Git 2.56 默认对这类 “视觉根节点” 增加缩进:
* root of one visible history
* unrelated commit
默认开启;--no-graph-indent切回旧渲染逻辑,也可以配置 log.graphIndent修改默认行为。
- 大量底层性能优化,消除性能断崖
多项内部改动解决大规模仓库的性能拐点:
-
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
要点总结
-
✅ git add --resolved:合并冲突专用暂存,自动校验冲突标记,不碰无关本地修改,提升合并安全。 -
✅ merge-base 算法提速:遍历提前终止,超大型 monorepo 数十倍提速,Linux 内核历史查询性能大幅改善。 -
✅ Path-walk repack 支持位图与 delta islands,服务端可启用,仓库体积最高可降 70%+。 -
✅ 实验命令增强: git history drop删除提交;git replay --linearize扁平化历史,不操作工作区。 -
✅ 新底层命令 git refs,统一引用操作。 -
✅ git branch --delete-merged批量清理已合并本地分支。 -
✅ git bisect run --reset-when-found自动回退检出状态。 -
✅ 部分克隆支持手动清理大 Blob,按需重拉。 -
✅ log 图形渲染、文件改名追踪逻辑优化。 -
✅ 大量底层性能优化,修复 O (N²) 瓶颈,超大仓库 diff、reftable 读写巨大提速。

