Docs Library

Git Merge 策略详解

系统介绍 Git 的合并策略——recursive、ort、octopus、ours、subtree——它们分别解决什么问题,以及如何选择。

适合谁看
  • 想先理解历史图再看命令的人
前置知识
  • 知道提交不是文件快照列表那么简单
常见风险
  • 把概念页当命令说明页使用

一句话理解

Git 的 merge 策略决定了"当两条分支需要整合时,Git 用什么算法计算最终内容"。选择合适的策略可以避免不必要的冲突和历史混乱。

合并前后对比左:合并前两条分支各自演进;右:合并后产生 merge commit,历史结构被保留。
合并前
main
ABC
feature
BDE
合并后
main
ABCM
feature
BDEM

Merge 策略总览

Git 支持以下几种 merge 策略:

策略默认场景适用分支数
ort(重构后的 recursive)默认策略2 个分支
recursive(旧版默认)已由 ort 替代2 个分支
octopus同时合并多个分支3+ 个分支
ours完全保留当前分支内容任意数量
subtree合并子项目到子目录2 个分支

ort(Ostensibly Recursive's Twin)

当前 Git 的默认 merge 策略,在 Git 2.33 中引入并替代了 recursive。

工作原理

  1. 找到两个分支的 merge base(共同祖先)
  2. 计算两个分支相对于 merge base 的变更
  3. 使用更高效的三方合并算法合并
  4. 检测并处理重命名、权限变更等

相比 recursive 的优势

  • 速度更快(用 C 重写了原本的 Python/Shell 合并逻辑)
  • 冲突检测更准确
  • 重命名检测更可靠
  • 内存使用更少

使用方式

# ort 是默认策略,无需显式指定
git merge feature/login

# 显式指定
git merge -s ort feature/login

recursive(递归策略)

Git 2.33 之前的默认策略,现在已被 ort 替代,但为了兼容性仍然保留。

工作原理

当两个分支有多个共同祖先时,recursive 会先把这些祖先合并成一个虚拟祖先,再基于这个虚拟祖先进行三方合并:

main:    A---B---C---D
              \
feature:       E---F

如果 merge base 不唯一,recursive 会先递归合并祖先再执行合并。

适用的配置参数

# 使用 recursive 策略
git merge -s recursive feature/login

# 设置合并时使用的相似度阈值
git merge -s recursive -X find-renames=70 feature/login

# 忽略空白差异
git merge -s recursive -X ignore-space-change feature/login

# 使用他们的版本处理冲突
git merge -s recursive -X theirs feature/login

# 使用我们的版本处理冲突
git merge -s recursive -X ours feature/login

octopus(八爪鱼策略)

用于一次合并多个分支。

工作原理

把多个分支依次应用到当前分支上。如果任何一个分支的合并产生冲突,octopus 会直接中止——它不适合有冲突的场景。

使用方式

# 同时合并三个功能分支
git merge feature/login feature/payment feature/report

Git 会自动选择 octopus 策略,因为涉及的分支数超过 2 个。

适用场景

  • 一次性合并多个独立、不冲突的特性分支
  • 主题分支的批量整合
  • 发布分支汇总

不适合的场景

  • 分支之间有代码冲突
  • 需要精细控制冲突处理

ours(保留当前策略)

完全保留当前分支的内容,忽略所有要合并进来的分支的变更。合并后的历史会显示这些分支被"合并"了,但内容不会改变。

使用方式

# 声明 feature 已经"合并",但不应用它的任何变更
git merge -s ours feature/experimental

适用场景

  • 废弃某个功能分支但保留历史记录
  • 已经用其他方式应用了变更,只想记录合并关系
  • 需要标记某个分支已经被"覆盖"

与其他策略的区别

注意 -X ours(策略选项)和 -s ours(策略本身)的区别:

  • -s ours:合并结果完全等于当前分支内容
  • -X ours(搭配 recursive/ort):有冲突时优先使用当前分支的版本

subtree(子树策略)

把被合并分支的内容合并到当前仓库的一个子目录中。

工作原理

它会自动检测被合并分支的内容应该被放到哪个子目录中,然后把变更映射到该子目录下。

使用方式

# 将 lib 仓库合并到当前仓库的 lib/ 目录下
git merge -s subtree lib/main

适用场景

  • 将一个独立的库作为子树集成到项目中
  • git subtree 命令配合使用维护子项目

如何选择 Merge 策略

日常开发

默认使用 ort(即默认 merge),不需要额外配置:

git switch main
git merge feature/login

批量合并

使用 octopus:

git merge feature/a feature/b feature/c

特殊场景

# 忽略空白差异的合并
git merge -X ignore-all-space feature/login

# 完全接受对方的版本(有冲突时)
git merge -X theirs feature/login

# 只记录合并关系,不改变内容
git merge -s ours feature/abandoned
不要对共享分支随意变更 merge 策略

日常开发推荐使用默认策略(ort)。除非你明确知道 -s ours-X theirs 等选项的副作用,否则不建议在生产共享分支上使用非默认策略。特别要注意 -s ours 会完全忽略对方分支的所有变更——它更适合废弃分支,而非日常合并。

策略选项速查

选项说明适用策略
ours冲突时使用当前分支版本recursive/ort
theirs冲突时使用被合并分支版本recursive/ort
patience使用更精确的 diff 算法recursive/ort
ignore-space-change忽略空白数量变化recursive/ort
ignore-all-space忽略所有空白差异recursive/ort
renormalize合并前规范化行尾recursive/ort
no-renames关闭重命名检测recursive/ort
find-renames=<n>设置重命名相似度阈值recursive/ort
subtree[=<path>]子树合并的变体recursive/ort

继续学习建议

理解 merge 策略后,建议继续学习:

  1. git merge 命令的完整参数
  2. Merge vs Rebase 的选择决策
  3. 三方合并(Three-way merge)的工作原理
  4. 冲突解决的策略和工具