前言
这么久以来不管是更新当前分支代码,还是合并代码,都是使用的merge,但也知道有rebase的操作,就是不理解其究竟有什么区别,且merge用了这么久没出过啥问题,就没深究过rebase。现在抽空出来,研究一下,实际rebase的使用场景还是挺多,而且这些场景下使用rebase的姿势也要比merge正确。
merge与rebase的区别
rebase会把你当前分支的 commit
放到公共分支的最后面,所以叫变基。就好像你从公共分支又重新拉出来这个分支一样。
举例:如果你从 master
拉了个feature
分支出来,然后你提交了几个 commit
,这个时候刚好有人把他开发的东西合并到 master
了,这个时候 master
就比你拉分支的时候多了几个 commit
,如果这个时候你 rebase master
的话,就会把你当前的几个 commit
,放到那个人 commit
的后面。
merge 会把公共分支和你当前的 commit
合并在一起,形成一个新的 commit
提交
使用 rebase 和 merge 的基本原则
- 下游分支更新上游分支内容的时候根据情况使用master或rebase
- 上游分支合并下游分支内容的时候使用 merge
- 更新当前分支的内容时一定要使用 --rebase 参数
上游和下游:一直有一个固定上游,就是master分支,所有分支向上追溯的根源都是master,所以上游和下游是相对的,上游就是从当前分支还新拉了一个分支,那当前分支就是上游,下游就是你从其他分支拉的最新分支。
现在有三个分支,master、merge_test、rebase_test分支来对三种场景进行演示
1.下游分支更新上游分支内容的时候根据情况使用master或rebase
-
master更新文件,push, 提交日志如下图:
-
merge_test
分支使用merge
更新master
分支的代码:因为下游分支一直在提交新的改动代码,所以想要更新上游分支时,如果使用merge的话,那会多出一行merge
的提交记录。
虽然没什么影响,中间插入这么一条记录,看起来时间线根本不好看。merge_test分支查看git日志如下图:
-
rebase_test
分支使用rebase
更新master
分支的代码:此时如果我们使用rebase
来更新master
的代码到开发分支,就是所谓的“变基”,将master的提交记录,全部迁移到当前开发分支,当前分支就是以master
为基础重新更新的分支。就像是当时从master
拉出来时一样,在开发分支会有创建分支之前,在上游分支的git提交记录。rebase_test
分支查看git日志如下图,就不会存在上面merge
操作更新后,多的那一行记录。
使用rebase
之后,如果直接使用git push origin rebase_test
发现是不好使的,会有问题提示说明,相对远程rebase_test
分支而言,本地仓库的rebase_test
分支的“基底”已经变化了,直接push
是不行的,所以确保没有问题的情况下必须使用--force
参数才能提交,这也就是官方对rebase
作为 “变基” 的解释(个人观点)
idea中在rebase
后push
会有以下提示,再次点击rebase
即可:
这里又会引发出另一个问题,一个文件的多次提交合并到当前分支都有冲突的话,有多少次提交与当前的分支有冲突,就会解决多少次冲突,而不是以合并前最近修改的结果来解决冲突,所以在一个文件多次修改一处地方后提交了多次代码日志,建议将多次提交日志压缩合并(squash
)到一条提交记录中,就可以只解决最近一条提交记录的冲突即可。
2.上游分支合并下游分支内容的时候使用 merge
这个操作切记不要使用rebase
了,因为下游全是基于上游开发的,所以上游使用merge
即可。
3.更新当前分支的内容时一定要使用 --rebase
参数
更新当前分支代码时,会有两种方式:
当前分支因为可能会有多个小伙伴同事在提交代码,所以要不定时的更新下当前分支的代码。以前习惯性的喜欢用merge
来pull
更新代码,也会发现每次pull
后,会多出一行提交记录:
Merge remote-tracking branch 'origin/merge_test' into merge_test
因为插入了上面这条提交记录,这样看起来整个分支的提交记录就被打乱了,整个提交记录也就不连贯了,所以建议使用rebase
来进行更新当前分支的代码。
使用 rebase
就感觉所有人都在同一条直线上开发一样,历史提交线会很清晰。
还有一个原因:Rebase the currenct branch on top of the incoming changes,把当前分支的基放在即将拉下来的change 的上面。它相当于后移了自己本地分支的检出commit~
以上是结合多个博客总结的,参考原文链接:
https://zhuanlan.zhihu.com/p/34197548
https://www.jianshu.com/p/4079284dd970