Fast-forward 是指 Master 合并 Feature 时候发现 Master 当前节点一直和 Feature 的根节点相同,没有发生改变,那么 Master 快速移动头指针到 Feature 的位置,所以 Fast-forward 并不会发生真正的合并,只是通过移动指针造成合并的假象。
git checkout master
git merge feautre556
Updating a1ec682..38348cc
Fast-forward
....... | 2+++
1 file changed, 2 insertions(+)
如果你注意上面的文字的话,你会发现 git 帮你自动执行了 Fast-forward 操作。分支变换过程如下:
通常功能分支(feature556) 合并 master 后会被删除,通过下图可以看到,通过 Fast-forward 模式产生的合并可以产生干净并且线性的历史记录:
通常,当合并的分支跟 master 不存在共同祖先节点的时候,这时候在 merge 的时候 git 默认无法使用 Fast-forward 模式
举个例子,master 分支已经比 feature001 快了2个版本,master 已经没办法通过移动头指针来完成 Fast-forward,所以在 master 合并 feature001 的时候就不得不做出真正的合并,真正的合并会让 git 多做很多工作,具体合并的动作如下:
补充:大家在 git log 看到很多类似:Merge branch 'feature001' into master 的 commit 就是 non-Fast-forward 产生的。
小结:
当执行rebase操作时,git会从两个分支的共同祖先开始提取待变基分支上的修改,然后将待变基分支指向基分支的最新提交,最后将刚才提取的修改应用到基分支的最新提交的后面。
操作原理:
需要注意的是这里的第三步一般会产生冲突,这时候就不是简单的迁移了,而是先将待迁移节点(这里为C3,C4,C5)依次逐个与最新节点进行冲突合并。 比如这里第一次冲突是C3与最新节点C8冲突,解决冲突之后得到节点C3`,而得到的这个节点此时也成为了最新节点。之后继续拿C4,C5节点重复此动作依次得到最新的节点。
即便是这里不会发生冲突,迁移后的节点commit的哈希值也已经发生变化,所以相应的节点才叫C3`,而不是C3。
也正是出于这个原因,一般建议是在待合并分支上(此例中为feature)进行rebase操作,而不是在主分支上,最后切换到主分支merge过去即可。原因是有时候可能会通过HASH值去回溯节点,如果在主分支进行了此操作,则HSAH值会发生变化,不利于回溯。
其实在使用者的视角里这里的整个过程说白了就像是把你feature分支上的节点依次重新更新到主分支上一样。
异同
首先二者都具备整合分支间变更的能力,但二者的实现手段却大不相同。git merge总是在推进提交历史,并不会影响提交的原始状态,而git rebase整合变更的方式则是对提交历史进行重写,但从结果上看,最后git rebase形成的节点C5`与git merge形成的节点C9完全相同。
优点:
rebase不产生新节点,当然也不会产生新的commit日志,但是merge过程中会产生一条几乎“无用”的Merge日志。使用rebase操作的最大好处在于你可以让项目提交历史变得非常干净整洁。首先,它消除了git merge操作所需创建的没有必要的合并提交。其次,rebase会造就一个线性的项目提交历史——也就是说你可以从feature分支的顶部开始向下查找到分支的起始点,而不会碰到任何历史分叉。
rebase产生冲突并合并冲突发生在你操作git rebase时,而合并冲突这个操作是你自己进行的;但是你提交合并申请的时候一般情况下会有评审,由评审者解决冲突,开发者人多的情况下工作量可想而知。
缺点:
rebase操作产生冲突需要依次逐个进行解决,重写提交历史可能引起混乱,对新手使用也不是很友好。
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。