同样是合并分支,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 信息。

相关推荐
小强19883 分钟前
为什么小程序中不能使用 window、document 或 jQuery?
后端
楼田莉子7 分钟前
仿Muduo的高并发服务器:LoopThread模块及其ThreadPool模块
linux·服务器·c++·后端·学习
二月龙9 分钟前
微信小程序页面栈限制解析与突破方案
后端
Rust研习社14 分钟前
你为什么总是入门 Rust 失败
开发语言·后端·rust
SamDeepThinking15 分钟前
批评下属不如当场展示解决方案
后端·程序员·团队管理
会笑的小熊34 分钟前
VScode项目推送到git仓库
ide·git·vscode
zhangfeng113336 分钟前
宝塔服务器完全可以安装 Git,进行版本管理,而且非常简单
运维·服务器·人工智能·git·编程
AskHarries1 小时前
GPT-Image-2(img2)到底能做什么?
后端
Leinwin1 小时前
GPT-5.5 Instant API接入教程:免费额度、速率限制与最佳实践
后端·python·flask
Xidaoapi1 小时前
从零搭建一个AI Agent:Python实战指南
后端