分支合并到b和b合并到a有区别吗
Posted 是石头ya
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分支合并到b和b合并到a有区别吗相关的知识,希望对你有一定的参考价值。
a分支合并到b分支和b合并到a有区别吗
一、背景
研究下关于 a 和 b 两个分支 a合并到b 和 b合并到a 有什么区别。
结论:不用纠结合并代码的时候谁合并谁,只是方向不一样
二、实验
有两个分支,分别是 feat_w8y 和 feat_617,最初都有共同的起始点,都是从c1这个revision(commit id)分叉出来的,feat_w8y分支上修改了代码向前进到c2 revision,而feat_617也修改同一行代码向前进到c3 revision。
由于修改了同一行代码,两个分支合并的时候会出现代码冲突。
现在来研究 “a合并到b” 和 “b合并到a” 有什么不同。
背景:
feat_w8y分支上将方法名由 getProfile
改成 getProfiles_byw8y
feat_617分支上将方法名改成 getProfiles_by617
-
feat_617上合并feat_w8y(即feat_617 <- feat_w8y),看到的冲突是
-
反方向合并(feat_w8y <- feat_617),得到
可以看到,其实完全是一样的,只是变更的内容的位置反过来而已
结论:不用纠结合并代码的时候谁合并谁,只是方向不一样
三、额外补充:合并时注意事项
使用命令行合并(或使用IDEA图形界面合并也同样存在如下问题)
git merge abc
和 git merge origin/abc
是不同的含义的!
-
一个是将本地的abc分支merge到当前分支,另一个是将origin的abc分支merge到当前分支
意思是如果abc和origin/abc所处的revision不同,则最终的合并结果是不同的!!!
-
另外非常非常非常需要注意的是
origin/abc
并不是远程的abc分支,而是本地的!!!意思是如果你不先git fetch 将远程的abc分支同步到本地 origin/abc 的话,合并出最终的结果是会有出入的!!!
比如:如果你本地的origin/abc处于c1,而刚刚别人推送了c2到origin/abc,如果你不git fetch将本地的origin/abc更新到c2,则merge用的也是c1,会出问题的!!
-
另外还有种写法
git merge remotes/origin/abc
,我本以为这个一定能合并到最新的abc分支,可是我错了。它的执行效果跟git merge origin/abc
是一样的!
以上使用IDEA图形界面操作了一遍,也存在这个问题。所以最终还是要有个好习惯,在merge代码的时候一定要先git fetch更新本地的,当你确认了本地的abc和orgin/abc是一样的时候,则随便用哪种方式merge都没问题。
四、思考
思考1:
有人可能看到这篇文章的时候会觉得做的实验这么少、例子这么少怎么能说明 “a合并b和b合并a相同只是方向相反、像镜子一样”。实际上,在生产中我是实验过的,是经过复杂的代码改变的验证的!!!
思考2
两个分支一定有一个共同的起点,这句话对吗?(共同起点指的是分叉出去之前共同的commit id)
我认为是正确的(但要排除掉这种对我们讨论无意义的情况:两个分支完全一样只是起了不同名字,或者由始到终都是合并后fast-forward这种,如 c1 -> c2 -> c3,a和b分支都在c3上,或者 “a分支在c2,b分支在c3”)
-
可能存在多个分叉点,存在一个最近的分叉点
看图有两个主线,上面a分支,下面b分支 可以看到分叉点是:c1,c6,c12 汇聚点是:c6,c10 结论:最近的分叉点是c12
思考3
如何看懂合并后的这些符号?
-
<<<<<<<
和=======
夹着的是HEAD的,=======
和>>>>>>>
夹着的是 feat_w8y 分支的内容 -
什么是HEAD的?HEAD在这里就是指HEAD所指向的commit,其实就是当前所在的分支。比如截图就是在feat_617上执行merge命令合并feat_w8y,所以HEAD是指feat_617分支
-
可以使用
git status
查询有什么文件冲突,也可以搜索<<<<<<<
定位到文件。下面是
git status
显示的结果 Unmerged paths 列出的就是冲突的文件On branch feat_w8y Your branch is up to date with 'origin/feat_w8y'. You have unmerged paths. (fix conflicts and run "git commit") (use "git merge --abort" to abort the merge) Unmerged paths: (use "git add <file>..." to mark resolution) both modified: src/main/java/com/wyf/test/test_pr_private/TestController.java no changes added to commit (use "git add" and/or "git commit -a")
-
使用
<<<<<<<
搜索的时候,注意是7个这样的符号,你如果搜少于一半,可能会误判需要解决的地方数量。
思考4
使用命令的方式合并分支跟使用IDEA图形化的合并,哪个更有优势呢?
-
比较差异的算法不同,有时候各自都会呈现比较奇葩的比较差异
- 比如有时只在a行后面追加了新的一行b,硬是显示为删除a行并添加了a、b两行(其实diff算法足够好的话应该展示为新增b行)
-
使用IDEA图形化一般更加直观,不过熟悉后其实两者差不多
-
使用IDEA解决代码冲突,分三栏,中间是最终结果,两边分别是两分支的代码
-
命令行和图形化解决代码冲突的过程比较明显的区别如下
如果A文件有冲突,IDEA图形化除了将冲突的部分列出来,不冲突的部分也列出来;但是使用命令行合并,直接就帮你把没冲突图的部分解决好了(就是用新版代替旧版)
什么是 “新版代替旧版”,就是新加的那行注释 “// 默认名字是default” 所在的revision比原来没有这个注释的revision要新,所以而且这个"变化"没有冲突所以就被自动应用了
补充
补充一个稍微更加复杂一些的合并
a分支合并到b分支,与b分支合并到a分支,看图,确实只是冲突内容调换了一下
如果使用IDEA图形化界面处理冲突,我也截了两个图
(其实也可以看到,实际也是调换了一下内容而已)
以上是关于分支合并到b和b合并到a有区别吗的主要内容,如果未能解决你的问题,请参考以下文章