同样是合并分支,git merge和rebase有什么区别

前言

在多人协作开发中,不同的开发者经常在不同的分支进行开发,最后会将变动合并到主分支上。在 git 中,merge 和rebase 都可以用来合并分支。那么,merge 和 rebase 又有什么不同呢。

merge

在 master 分支创建一个名为 aqi 的文件,先写入1,然后执行 add、commit 提交到本地仓库,然后分两次分别写入2和3,执行上述操作。在整个过程中,文件 aqi 一共被 commit 提交了三次,也就是有三次提交记录。

然后在此基础上,创建 dev 分支,这时候的 dev 就像是 master 分支的"镜像",两个分支具有相同文件内容以及提交记录。

如果 master 分支不做任何变更,这时候我在 dev 变更 aqi 文件的内容,新增一行4,然后提交到本地仓库。

在可视化界面中可以看到 dev 分支基于是基于 master 的第三次提交进行的变更。

这时候切换到 master 分支合并 dev 分支的变更。

bash 复制代码
git merge dev

这样 dev 分支的变更就被合并到 master 分支上了。

fast-forward模式

fast-forward 是 merge 的快进模式,如果当前的分支没有任何新的commit,而另一个分支包含了一些新提交时,git 会直接将当前分支快进到目标分支的最新提交,而不创建额外的合并提交。。

例如在上面的提交记录中,master 内容是 1、2、3,dev 文件内容的是 1、2、3、dev4。dev 是全包含于 master 的,所以这里使用的就是快进模式。

从上图可以看到,提示中有 fast-forward,表示直接将两个分支合并,不创建新的 commit,移动两个分支的指针指向 dev 的 commit,此时 dev 的 commit 属于两个分支。

通过 git log 查看提交日志,master 分支已经有了 dev 之前的提交信息。这里要注意的是,master 分支直接使用了 dev 分支的提交信息。

如图,master 分支的 HEAD 指向 dev4 这个提交信息。

no-fast-forward模式

no-fast-forward模式:

  1. --no-ff 指定 no-fast-forward 模式合并分支
  2. 如果两个分支在同一个基点之后都有各自的提交历史,合并时会使用非快进模式

1. --no-ff

使用 git reset 将 master 分支恢复到合并前的状态。

此时 master 分支只有3个提交信息,dev 是4个。使用 --no-ff 指定 no-fast-forward 模式合并分支。

bash 复制代码
git merge dev -m'master4' --no-ff

我们知道 -m 是 commit 时,用来指定提交信息的参数。这里在合并之后,使用 git log 查看提交日志,除了有 dev4 这个提交信息,也多了上面命令指定的commit信息。

也就是说,在 --no-ff 模式下,当前分支合并之后会新建一个commit。我们可以查看可视化提交信息来理解。

如图,这里 master 分支的 HEAD 不再指向 dev4,而是指向合并后新建的commit。

2. 新提交

我在 master 分支上,基于提交3创建了一个文件作为新变更(修改同一文件会冲突),然后提交信息为 master4。

如图所示,master 和 dev 分支都有共同的祖先,都基于3节点做了新的变更提交。这里执行 git merge dev 合并分支。

如图所示,和指定 --no-ff 相同,都创建了新的提交信息。

rebase

git rebase 是另一种合并分支的方式,它通过将一个分支的提交移到另一个分支的基础上,重新应用这些提交。与 git merge 不同的是,git rebase 不会创建合并提交,而是将两个分支的提交历史线性化,重新排列提交记录。

和上面 merge 的前置条件一样,在 master 中有三次 git 提交记录,在此基础上,我们创建 dev 分支,然后变更文件再次提交一次。这时我使用 rebase ,将 dev 分支合并到 master 分支。

这个结果就和 git merge 的 fast-forward 模式一样,不会生成自己的提交信息,而是使用 dev 分支的提交信息。

但是在多人协作的开发中,很少有这种全包含的情况,基本上就是从一个 commit 的基点拉出分支,然后各自开发各自的,最后开发完成进行合并。

merge 合并

回退到合并前的状态,master 和 dev 分支都基于第三次提交之后再做变更,这时候两个分支提交信息如下图(绿色是master)。

这时执行 git merge 合并分支。因为 master 和 dev 两个分支在同一个基点之后,都有各自的提交历史,这时 git merge 合并分支,就会生成一个新的 commit 信息,然后 master 将 HEAD 指向最新的这个提交。

rebase 合并

再次回退到 merge 合并前的状态,执行 git rebase dev 来合并。

如图,因为 dev4 的变更提交早于 master4 的提交,所以 dev4 的提交就被合并到了 master4之前。也可以从可视化界面查看提交日志:

如图,rebase 合并不会创建新的 commit 信息。

相关推荐
goTsHgo23 分钟前
在 Spring Boot 的 MVC 框架中 路径匹配的实现 详解
spring boot·后端·mvc
waicsdn_haha34 分钟前
Java/JDK下载、安装及环境配置超详细教程【Windows10、macOS和Linux图文详解】
java·运维·服务器·开发语言·windows·后端·jdk
Q_192849990644 分钟前
基于Spring Boot的摄影器材租赁回收系统
java·spring boot·后端
良许Linux1 小时前
0.96寸OLED显示屏详解
linux·服务器·后端·互联网
求知若饥1 小时前
NestJS 项目实战-权限管理系统开发(六)
后端·node.js·nestjs
左羊1 小时前
【代码备忘录】复杂SQL写法案例(一)
后端
gb42152872 小时前
springboot中Jackson库和jsonpath库的区别和联系。
java·spring boot·后端
程序猿进阶2 小时前
深入解析 Spring WebFlux:原理与应用
java·开发语言·后端·spring·面试·架构·springboot
颜淡慕潇2 小时前
【K8S问题系列 |19 】如何解决 Pod 无法挂载 PVC问题
后端·云原生·容器·kubernetes