git pull = git fetch + git merge
git pull --rebase = git fetch + git rebase

现在有两个分支:test和master,假设远端的master的代码已经更改了(在B基础上变动:C,F),test的代码更改了要提交代码(在B基础上变动:D,E),如下图:

      D---E test
      /
 A---B---C---F--- master

问题就来了,如果C,F和D,E的更改发生冲突,那么就需要我们合并冲突了,下面我们来看看git merge和git rebase怎么合并的

git merge:

       D--------E
      /          \
 A---B---C---F----G---   test, master
 
git rebase
	git --rebase会将两个分支融合成一个线性的提交,不会形成新的节点(下面是在master上rebase)
 A---B---D---E---C‘---F‘---   test, master

rebase好处
	想要更好的提交树,使用rebase操作会更好一点。
	这样可以线性的看到每一次提交,并且没有增加提交节点。
	merge 操作遇到冲突的时候,当前merge不能继续进行下去。手动修改冲突内容后,add 修改,commit 就可以了。
	而rebase 操作的话,会中断rebase,同时会提示去解决冲突。
	解决冲突后,将修改add后执行git rebase –continue继续操作,或者git rebase –skip忽略冲突。

rebase详解

  • 待变基分支和基分支:

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

  • 两个分支master和feature,其中feature是在提交点B处从master上拉出的分支,master上有一个新提交M,feature上有两个新提交C和D。
    在这里插入图片描述

git checkout feature 
git rebase master // 这两条命令等价于git rebase master feature

下图为变基后的提交节点图:
在这里插入图片描述

  • 当在feature分支上执行git rebase master时,git会从master和featuer的共同祖先B开始提取feature分支上的修改,也就是C和D两个提交,先提取到。然后将feature分支指向master分支的最新提交上,也就是M。最后把提取的C和D接到M后面,但这个过程是删除原来的C和D,生成新的C’和D’,他们的提交内容一样,但commit id不同,feature自然最后也是指向D’
  • rebase字面意思就是"变基",可以直接理解为改变基底。feature分支是基于master分支的B拉出来的分支,feature的基底是B。而master在B之后有新的提交,就相当于此时要用master上新的提交来作为feature分支的新基底。
    • 注意,如果master上在B以后没有新提交,那么就还是用原来的B作为基,rebase操作相当于无效,此时和git merge就基本没区别了,差异只在于git merge会多一条记录Merge操作的提交记录。

其他案例:

  • 现在假设main分支内新增的内容与你正在开发的新功能有关。
  • 为了把main分支里新增的代码应用在你的feature分支,你有两种方法:merge 和 rebase
    在这里插入图片描述

使用merge:

git checkout feature
git merge main
或
git merge feature main
  • 这会在feature分支中创建一个合并提交,这次提交会连结两个分支的提交历史,在分支图示结构中看起来像下面这样
    在这里插入图片描述

使用rebase:

git checkout feature
git rebase main
  • 这些操作会把feature分支的起始历史放到main分支的最后一次提交之上,也达成了使用main分支中新代码的目的。但是,相对于merge操作中新建一个合并提交,rebase操作会通过为原始分支的每次提交创建全新的提交,从而重写原始分支的提交历史
    在这里插入图片描述

rebase慎用场景:
场景一:

  • 不要在公共分支上使用它
  • 如果把main分支rebase到feature分支之上。
    • 情况一:rebase命令会把main分支中的所有提交都放到feature分支的提交记录顶端。问题在于这个改变目前只出现在你的本地仓库。其他开发者仍然在原来的main分支上进行开发。由于rebase会产生全新的提交记录,所以Git会认为现在你本地的main分支与所有其他人的产生了分叉。
    • 情况二:往公共分支上合代码的时候,使用merge。如果使用rebase,那么其他开发人员想看主分支的历史,就不是原来的历史了,历史已经被你篡改了。比如张三和李四从共同的节点拉出来开发,张三先开发完提交了两次然后merge上去了,李四后来开发完rebase上去(注意:李四需要切换到主分支,然后执行git rebase,然后再git push到远端),则李四的新提交变成了张三之前新提交的新基底,本来李四的提交是最新的,结果最新的提交显示反而是张三的,就乱套了
      • 也就是换基底了。

在这里插入图片描述

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐