• 分支合并到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 abcgit 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
      
      • 1
      • 2
      • 3
      • 4
      • 5
    思考3

    如何看懂合并后的这些符号?
    在这里插入图片描述

    • <<<<<<<======= 夹着的是HEAD的,=======>>>>>>> 夹着的是 feat_w8y 分支的内容

    • 什么是HEAD的?HEAD在这里就是指HEAD所指向的commit,其实就是当前所在的分支。比如截图就是在feat_617上执行merge命令合并feat_w8y,所以HEAD是指feat_617分支

    可以看到GitHub自己的编辑器显示的就不是像 HEAD 这么难理解的,直接展示为分支名,如feat_617和feat_w8y
    在这里插入图片描述

    • 可以使用 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 ..." 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")
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
    • 使用 <<<<<<< 搜索的时候,注意是7个这样的符号,你如果搜少于一半,可能会误判需要解决的地方数量。

    思考4

    使用命令的方式合并分支跟使用IDEA图形化的合并,哪个更有优势呢?

    • 比较差异的算法不同,有时候各自都会呈现比较奇葩的比较差异

      • 比如有时只在a行后面追加了新的一行b,硬是显示为删除a行并添加了a、b两行(其实diff算法足够好的话应该展示为新增b行)
    • 使用IDEA图形化一般更加直观,不过熟悉后其实两者差不多

    • 使用IDEA解决代码冲突,分三栏,中间是最终结果,两边分别是两分支的代码

    • 命令行和图形化解决代码冲突的过程比较明显的区别如下

      如果A文件有冲突,IDEA图形化除了将冲突的部分列出来,不冲突的部分也列出来;但是使用命令行合并,直接就帮你把没冲突图的部分解决好了(就是用新版代替旧版)

      什么是 “新版代替旧版”,就是新加的那行注释 “// 默认名字是default” 所在的revision比原来没有这个注释的revision要新,所以而且这个"变化"没有冲突所以就被自动应用了

      在这里插入图片描述

      在这里插入图片描述

    补充

    补充一个稍微更加复杂一些的合并
    a分支合并到b分支,与b分支合并到a分支,看图,确实只是冲突内容调换了一下
    在这里插入图片描述
    在这里插入图片描述

    如果使用IDEA图形化界面处理冲突,我也截了两个图
    (其实也可以看到,实际也是调换了一下内容而已)
    在这里插入图片描述
    在这里插入图片描述

  • 相关阅读:
    简述快速失败(fail-fast)和安全失败(fail-safe)的区别 ?
    python激活虚拟环境env报错:no such file or directory: env/Scripts/activate
    Java中常见的限流算法讲解以及实现思路
    【SQLite】一、SQLite简介——MySQL的简洁版
    Python元学习-通用人工智能的实现 第3章 阅读笔记
    基于Spring Boot+Vue的健身房管理系统(协同过滤算法、功能非常多)
    虚拟机搭建开发环境jdk、mysql、redis、nacos、nginx
    神奇的 \u000d
    [附源码]Python计算机毕业设计Django演唱会门票售卖系统
    linux查看所有用户
  • 原文地址:https://blog.csdn.net/w8y56f/article/details/126692816