---
sidebar_label: '合并模式简介'
sidebar_position: 4    
---

# 合并模式简介

在审阅人审查完开发者提交的代码变更后，便可以决定是否将这些提交合并进主分支`master`中。

然而，对于不同分支间的提交合并，存在多种合并模式，下图为GitLink中支持的合并模式，包括**合并请求**、**变基并合并**、**变基合并 --no-ff**以及**压缩提交并合并**四种。

![合并模式](/img/PR/imagePR5.png)

1. **合并请求**

**合并请求**是最常用的合并模式，以下图为例，开发者在主分支`master`的提交3处拉取了开发分支`dev`，然后分别提交了A、B、C，然后在`master`分支上进行合并。

快进合并前：

![快进合并前](/img/PR/imagePR6.png)

快进合并后：

![快进合并后](/img/PR/imagePR7.png)

**注意**：可以看到，合并的过程就是直接把`master`指针移动到了`dev`指针处，这种合并被称为**快进（fast-forward）**，之所以出现这种情形是因为在提交3之后，`master`分支上没有新的提交，所以通过直接快进`master`指针就可以完成合并；但如果在`master`分支上也有新的提交，就需要进行实质性的合并了，如下面两幅图所示：

在合并前，`dev`分支上提交A之后、提交B之前，`master`分支上提交了4，这时合并`dev`分支就不能简单地快进移动，而是要比较两个分支上更改的内容，然后进行合并；

非快进合并前：

![非快进合并前](/img/PR/imagePR8.png)


合并之后，提交A、B、C都会按时间线加入`master`的提交记录中，并且会生成一个新的提交D，用于记录合并这件事情；此外，如果合并过程中发生了冲突，即两个分支对同一个文件进行了修改，则需要手动处理冲突；这种合并方式就是**非快进（no fast-forward）**，这也是**合并请求**模式下的默认方式！

非快进合并后：

![非快进合并后](/img/PR/imagePR9.png)

为了方便理解，可以以线性方式查看合并后的`master`分支上的提交记录

![线性的提交记录](/img/PR/imagePR10.png)

**总结**：在**合并请求**模式下，默认采用**非快进**合并开发分支到`master`分支上，而**非快进**方式会生成一个特殊的提交用于记录此次合并事件！

2. **变基并合并**

从**合并请求**后`master`分支上的提交记录可以看出，两个分支的提交记录可能会交叉在一起，这可能会给后续开发带来困扰，而**变基并合并**可以解决这个问题。

**变基并合并**包括两个操作：**变基**、**合并**。首先是变基，以下图为例，`dev`分支是从提交3处拉取出来的，所以提交3就是`dev`的基，而变基操作就是改变`dev`的基，使其变为`master`分支上最新的一次提交。当然，变基过程中可能会出现冲突，则需要手动处理。

变基前：

![变基前](/img/PR/imagePR8.png)

变基后、合并前：

![变基后_合并前](/img/PR/imagePR11.png)


`dev`分支变基之后，`master`分支就没有“更新”的提交了，所以此时进行合并，就得到了如下的结果

合并后：

![合并后](/img/PR/imagePR12.png)

**总结**：在**变基并合并**模式下，开发分支`dev`可以先进行变基操作，使其上的提交看起来都是在`master`分支最新的提交基础上进行的，然后再通过**快进**方式合并回`master`分支，从而起到整理提交记录的作用！

3. **变基合并 --no-ff**

因为**变基并合并**进行合并操作时，默认采用**快进**方式，这样在`master`分支上就没有一个特殊的提交用于记录这次合并事件，所以可以使用`--no-ff`（**no fast-forward**）选项申明采用**非快进**方式进行合并。

`--no-ff`合并前：

![--no-ff合并前](/img/PR/imagePR11.png)

`--no-ff`合并后：

![--no-ff合并后](/img/PR/imagePR13.png)

**总结**：通过`--no-ff`选项，可以显式声明在合并时采用**非快进**方式，这样就可以在`master`分支中添加一个记录合并事件的提交！

4. **压缩提交并合并**

在`dev`或者`feature`这样的开发分支中，开发者为了完成某个需求会进行多次提交，然而这些琐碎的提交信息在合并回`master`分支后，会使`master`上的提交记录臃肿混乱，所以需要在合并前，对这些提交进行压缩。如图所示，压缩操作是在`master`分支上进行的，本质是将`dev`分支上进行的变更施加到`master`分支维护的文件上，然后将这些修改用新的提交5保存，最后提交。

压缩前：

![压缩前](/img/PR/imagePR8.png)

压缩后、提交前：

![压缩后_提交前](/img/PR/imagePR14.png)

提交后：

![提交后](/img/PR/imagePR15.png)

**总结**：在合并前，先对开发分支上的琐碎提交进行压缩，可以使`master`分支上的提交信息更简洁，但是要注意，这种合并模式本质上是`master`分支一次性保存`dev`上的变更，并创建新的提交记录这些变更，所以提交者发生了变化！