git merge和git rebase区别

前言

git merge 命令,可以将其中一个分支的代码合并到另一个分支中,其实还有另一种方法,通过 git rebase命令也可以实现,但是两者的实现方式还是有很大差异的。

先说结论:

  • merge 是一个合并操作,会将两个分支的修改合并在一起,默认操作的情况下会提交合并中修改的内容
  • merge 的提交历史记录了实际发生过什么,关注点在真实的提交历史上面
  • rebase 并没有进行合并操作,只是提取了当前分支的修改,将其复制在了目标分支的最新提交后面
  • rebase 操作会丢弃当前分支已提交的 commit,故不要在已经 push 到远程,和其他人正在协作开发的分支上执行 rebase 操作
  • merge 与 rebase 都是很好的分支合并命令,没有好坏之分,使用哪一个应由团队的实际开发需求及场景决定

image-20211104214737342

先来说说 git merge的实现方式

如上图所示,我们有两个分支,master 分支和 test 分支,test 分支是基于 master 分支在B处的提交节点创建的,在创建后 master 分支又经过迭代提交了两次,从C到D节点,test 分支也基于B往前继续更新了两次,到了F节点。两者从B开始就走向了分叉。

这时如果我们想将 test 分支合并到 master 分支,通过 merge 是如何工作的呢?

//将分支切换到master分支
git checkout master
​
//把test分支合并到master分支
git merge test
复制代码

image-20211104215627579

从图中可以看到,这里生成了一个新的提交G,是怎么生成的呢? merge 命令 它会把两个分支的最新快照(F、ED、C)以及二者最近的共同祖先(B)进行三方合并,合并的结果是生成一个新的快照G(并提交)。

通常,合并分支时,如果可能,Git会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息。

如果要强制禁用Fast forward模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息。

合并分支时,加上--no-ff参数表示禁用Fast forward,就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward合并就看不出来曾经做过合并。

git rebase实现方式

//将分支切换到master分支
git checkout master
​
//把test分支合并到master分支
git rebase test
复制代码

从图就可以看出和 merge 命令不同

这里有个名词定义我们先简单说明一下

  • test:基分支、目标分支
  • master: 待变基分支,当前分支

官方解释: 当执行 rebase 操作时,git 会从两个分支的共同祖先开始提取待变基分支上的修改,然后将待变基分支指向基分支的最新提交,最后将刚才提取的修改应用到基分支的最新提交的后面。

这句话听起来可能绕绕的,不用怕,听小蛋给你好好翻译翻译:

我们结合具体例子来说明,当我们在master (待变基分支)上执行git rebase test(基分支)时,git就会从两者的共同祖先B开始,提取 master 分支上的修改,也就是 C,D 两个 commit ,提取到之后 git 会先保存起来,然后将master 分支指向 test 分支最新提交的节点,也就是F节点,然后把提取到的 C,D 接到F后面,在这个过程当中,会删除原来的C,D commit 记录,生成新的C‘,D',虽然C',D'和原来的C,Dcoommit的内容是一样的,但是 commit id 是不同的。

rebase 操作如果用一句话进行解释就是改变基底。master 分支原来的基底是A,现在变成了以 test 分支最新的提交F做为新的基底了。

总结

merge 和 rebase 这两者哪种操作更好,这是取决于不同的场景的。

当我们拉取公共分支最新代码的时候建议使用rebase,也就是git pull -rgit pull --rebase(git pull默认是用merge),但有个缺点就是 rebase 以后我就不知道我的当前分支最早是从哪个分支拉出来的了,因为基底变了嘛。(如果使用 merge ,多出无意义的一条提交记录)。

往公共分支上合代码的时候,使用 merge 。(如果使用 rebase ,那么其他开发人员想看主分支的历史,就不是原来的历史了,历史已经被你篡改了),例如主分支是 master 分支,小蛋我有一个 egg 分支,我在 egg 分支上写了很多垃圾代码,然后这时候我把 egg 分支通过 rebase 命令合并到 master 分支,那对于 master 分支来说,它之前到提交历史就没了,别的同事突然想看 master 分支以前的提交历史,其实就看不到了,发现只能看到我 egg 的提交历史,估计同事会把我的 egg 捏碎的,这种傻事可不要干哟。

 

转自:https://juejin.cn/post/7026724793047220254

posted @ 2022-04-05 00:45  收手吧阿祖  阅读(724)  评论(0编辑  收藏  举报