在 Git 中,合并(Merge) 是将一个分支的更改合并到另一个分支的过程。合并通常用于整合不同分支的开发成果,使代码保持最新并同步。本章将介绍合并的基本操作、如何处理合并冲突、不同的合并策略,以及 Git 对合并的处理方式。

10.1 合并的例子

10.1.1 为合并做准备

在合并之前,通常需要先更新目标分支,确保合并不会引入不必要的冲突。例如,要合并 feature 分支到 main,先切换到 main 并拉取最新代码:

  1. git checkout main
  2. git pull origin main

10.1.2 合并两个分支

执行合并操作,将 feature 分支合并到 main

  1. git merge feature

如果 feature 分支和 main 没有分叉(即 main 直接可以“快进”到 feature),Git 会执行快进合并(Fast-forward Merge),不会生成新的合并提交。

10.1.3 有冲突的合并

如果 mainfeature 之间有不同的修改,Git 会创建一个新的合并提交(Merge Commit)。如果发生冲突,Git 会提示:

  1. CONFLICT (content): Merge conflict in file.txt

此时需要手动解决冲突,编辑冲突的文件后执行:

  1. git add file.txt
  2. git commit -m "解决合并冲突"

10.2 处理合并冲突

当 Git 无法自动合并文件时,就会发生合并冲突(Merge Conflict)

10.2.1 确定冲突的文件

执行合并后,使用 git status 查看冲突文件:

  1. git status

输出示例:

  1. both modified: file.txt

表示 file.txt 在两个分支中都有修改,需要手动解决。

10.2.2 检查冲突

打开冲突文件,会看到类似的标记:

  1. <<<<<<< HEAD
  2. 这里是 main 分支的内容
  3. =======
  4. 这里是 feature 分支的内容
  5. >>>>>>> feature
  • HEAD 代表当前分支(main)的代码
  • ======= 分隔两个版本的代码
  • >>>>>>> 之后的是 feature 分支的代码

10.2.3 Git 是如何追踪冲突的

Git 通过 三方合并(Three-way Merge) 追踪冲突:

  • main 的最新提交
  • feature 的最新提交
  • 两者的共同祖先

通过这些信息,Git 确定冲突区域,并要求用户手动解决。

10.2.4 结束解决冲突

  1. 编辑冲突文件,删除冲突标记,保留正确的代码。
  2. 添加解决后的文件:

    1. git add file.txt
  3. 提交合并:

    1. git commit -m "解决合并冲突"

10.2.5 中止或重新启动合并

如果决定放弃合并,可以使用 git merge --abort 取消合并:

  1. git merge --abort

如果合并过程中出现错误,可使用 git reset --hard 回滚到合并前的状态(谨慎使用!):

  1. git reset --hard HEAD

10.3 合并策略

Git 提供不同的合并策略,以应对不同的场景。

10.3.1 退化合并(Fast-forward Merge)

如果 featuremain 的直接后继版本,Git 会执行快进合并:

  1. git merge --ff feature

这种方式不会创建额外的合并提交,但如果想保留合并记录,可以使用 --no-ff

  1. git merge --no-ff feature

10.3.2 常规合并(Three-way Merge)

如果 featuremain 发生了分叉,Git 会创建一个新的合并提交:

  1. git merge feature

10.3.3 特殊提交(Squash Merge)

git merge --squash 允许合并多个提交为一个提交,不会生成合并历史:

  1. git merge --squash feature
  2. git commit -m "合并 feature 分支的所有更改"

10.3.4 应用合并策略

不同场景适用于不同的合并方式,例如:

  • 短期分支 → 使用 --squash
  • 长期维护分支 → 使用 --no-ff
  • 合并多个开发分支 → 使用 rebase(下一章介绍)

10.3.5 合并和重新排序

如果希望在合并前重新整理提交记录,可以使用 git rebase 代替 git merge,详情见下一章。


10.4 Git 怎么看待合并

Git 在合并时,实际上是在操作 Git 对象模型(Git Object Model),主要涉及 提交(Commit)、树(Tree)和合并提交(Merge Commit)

10.4.1 合并和 Git 的对象模型

在 Git 内部,合并实际上是创建了一个新的提交,该提交有两个父提交。例如:

  1. * a1b2c3d (HEAD -> main) 合并 feature 分支
  2. |\
  3. | * f4e5g6h (feature) 新功能
  4. |/
  5. * 9d8e7f6 (main) 之前的提交

合并提交 a1b2c3d 具有两个父提交 9d8e7f6f4e5g6h

10.4.2 压制合并

如果不想保留分支的历史记录,可以使用 git rebase 代替 git merge,这将在下一章介绍。


结论

本章介绍了 Git 的合并操作,包括如何合并分支、解决合并冲突,以及不同的合并策略。合并是 Git 版本控制中最常用的操作之一,掌握合并技巧能够提高代码管理的效率。