Git合并分支超详细解释

Git合并分支超详细解释摘自朱双印老师博客 http www zsythink net archives 3470 在执行 合并 操作时 我们可以根据具体情况 选择不同的合并模式去合并 不同的合并模式对应了不同的命令参数 而且在合并的过程中 还可能遇到 冲突 为了说明白原理 我们先来看一些示意图此示意图并没有涉及到任何合并操作 而是描述了合并分支之前 两个分支的创建过程 上图中的第 1 步表示已经存在的一条分支 这条分支的名字是 base 第 2 步表示基于 base 分支 创建了 new 分支 此时 base 分支的指针和 new 分支的

摘自朱双印老师博客http://www.zsythink.net/archives/3470

在执行”合并”操作时,我们可以根据具体情况,选择不同的合并模式去合并,不同的合并模式对应了不同的命令参数,而且在合并的过程中,还可能遇到”冲突”。

上图中的第1步表示已经存在的一条分支,这条分支的名字是base。

第2步表示基于base分支,创建了new分支,此时,base分支的指针和new分支的指针都指向了最新的提交。

第3步表示我们在new分支中创建了新的提交。

第4步表示base分支也产生了新的提交,new分支也产生了新的提交,两个分支的指针分别指向了自己分支的最新提交,换句话说就是,从分叉点开始以后,两个分支各自产生了属于自己的提交。

我们先聊聊图示一,图示一表示将new分支合并到base分支上,合并操作完成后,会产生一个新的提交(蓝色提交),这个新提交就是合并后的提交,它包含了两个分支中的最新代码,并且将它们合并到了一起,这个提交就是我们想要的合并后的状态,base分支的指针会指向这个新的蓝色提交,而new分支的指针则没有移动位置,仍然指向了new分支的最新提交(绿色提交)。为什么base分支的指针会指向最新的蓝色提交,而new分支的指针却保持原位呢?我们可以这样理解,在合并之前,base分支和new分支都有属于自己独有的提交(最新的黄色提交只属于base分支,绿色提交只属于new分支),如果我们是把new分支合并到base分支上,就表示要把只属于new分支上的变更合并到base分支上,对于base分支来说,会有新的变更进入(原来只属于new分支的变更对于base分支来说就是新变更),所以,base分支需要一个新的提交(蓝色提交)来对应变化后的状态,于是,base分支的指针会指向最新产生的合并提交(蓝色提交),而对于new分支来说,并没有任何内容发生变动,所以new分支的指针仍然保持原位。

图示二表示将base分支合并到new分支上,合并后会产生一个新的合并提交(蓝色提交),这个蓝色提交对应了合并后的状态,这个新的蓝色提交属于new分支,而不属于base分支,因为我们是把base分支合并到new分支上,这表示只属于base分支的变更会加入到new分支中,对于new分支来说,内容会发生变化,new分支需要一个新的提交来对应变化后的状态,而这个新的提交正是合并后产生的蓝色提交,于是,new分支将指针指向了蓝色提交,base分支的指针仍然保持原位。

你肯定已经总结出了规律,规律就是,在上述情况下,合并后的新提交属于合并到的目标分支。

在这里插入图片描述
第5步代表使用”Fast-forward”的方式合并后的样子,你肯定已经看明白了,由于基于base分支创建new分支以后,base分支中并没有产生任何新的提交,如果此时想要将new分支合并到base分支,只需要将base分支的指针指向到new分支的最新提交,即可让base分支包含new分支中的所有新变更。

我们换个方式再解释一遍,new基于base创建,new新产生的所有变更都包含在上图中的绿色提交中,将new合并到base,就表示将new中的变更(所有绿色提交中包含的变更)也加入到base中,让绿色提交属于base分支最快的方法就是直接将base分支的指针直接指向最新的绿色提交。

“Fast-forward”的合并方式不会在base分支中产生任何合并提交(即不会产生示意图中的蓝色提交),而是利用了指针的移动,快速的实现了将new分支合并到base分支中的目的。


为了能够更加方便的进行演示,我们来创建一个测试仓库,在测试仓库的master分支中创建一些基础的可以用于测试的提交,操作如下

$ git init test_repo Initialized empty Git repository in D:/workspace/git/test_repo/.git/ $ cd test_repo/ $ echo "test1" > m1 $ echo "test11" > m11 $ git add -A $ git commit -m "Initializes files of module 1" [master (root-commit) 0da419c] Initializes files of module 1 2 files changed, 2 insertions(+) create mode  m1 create mode  m11 $ echo "test2" > m2 $ echo "test22" > m22 $ git add -A $ git commit -m "Initializes files of module 2" [master 5b8c4c8] Initializes files of module 2 2 files changed, 2 insertions(+) create mode  m2 create mode  m22 

此处假设,测试仓库中的这些测试文件就是我的程序代码,假设我的程序由两个模块组成,模块一和模块二,m1文件和m11文件属于模块一,m2文件和m22文件属于模块二,我会为模块一和模块二分别创建两个分支,以便针对两个模块的修改互不影响,当我需要一份完整的代码时,会将模块一和模块二对应的分支合并到master分支中,以便从master分支获取到相对完整的代码,现在,我们需要分别为两个模块创建分支,b1分支和b2分支,操作如下:

$ git status On branch master nothing to commit, working tree clean $ git branch b1 $ git branch b2 

现在,我切换到b1分支,修改一些文件,模拟针对模块一代码的修改工作,并且在b1分支上创建提交,操作如下:

$ git checkout b1 Switched to branch 'b1' $ cat m1 test1 $ echo "test m1" >> m1 $ cat m1 test1 test m1 $ git add m1 $ git commit -m "modify m1" [b1 be27bc9] modify m1 1 file changed, 1 insertion(+) 

同样,切换到b2分支,进行一些修改,模拟针对模块二的修改。操作如下

$ git checkout b2 $ cat m2 test2 $ cat m22 test22 $ echo "test m2" >> m2 $ echo "test m22" >> m22 $ cat m2 test2 test m2 $ cat m22 test22 test m22 $ git add -A $ git commit -m "modify module2" [b2 a73e5ca] modify module2 2 files changed, 2 insertions(+) 

如上图所示,b1分支和b2分支分别产生了属于自己的独有提交,也就是说,通过上述操作,这两个提交中分别存放了两个模块的最新代码,master分支中不包含这两个模块中任何一个模块的最新代码,如果我想要将两个模块的最新代码汇聚到master分支中,只需要将b1分支和b2分支合并到master分支中即可,那么具体该怎么操作呢?

如果你想要的将A分支合并到B分支,就需要先检出到B分支,然后再执行合并命令将A分支合并进来,也就是说,需要先检出到目标分支,再执行合并命令

先以合并b1分支为例,看看怎样将b1分支合并到master分支,具体操作如下:

#如果我们想要将某个分支的代码合并到master分支,需要先切换到master分支 $ git checkout master Switched to branch 'master' #查看一下m1文件的内容,并不是模块一最新的文件内容,m1的最新版本目前只存在于在b1分支中 $ cat m1 test1 #使用如下命令即可将b1分支合并到当前分支(当前分支是master分支),git merge命令就是用于合并分支的命令,此命令会将指定的分支合并到当前分支。 $ git merge b1 Updating 5b8c4c8..be27bc9 Fast-forward m1 | 1 + 1 file changed, 1 insertion(+) 

从上述命令的返回信息可以看出,当我们把b1分支合并到master分支时,git默认使用了”Fast-forward”模式,这是因为git发现,b1分支是基于master分支创建的,并且master分支并没有产生属于自己的独有的提交,所以,当我们需要把b1分支合并到master分支时,只需要将master的指针指向b1分支的最新提交即可,使用”gitk –all”查看图形化界面,如下:

在这里插入图片描述
正如我们所想,master分支的指针指向了b1分支的最新提交,也就是说,此时b1分支已经合并到了master分支中。

再次查看master分支中的m1文件内容,发现m1的内容已经变成了最新的版本

$ cat m1 test1 test m1 

如上述操作所示,我们把b1分支合并到了master分支中,master分支中已经包含了模块一的最新版本的代码,但是目前,master分支中还不包含模块二的最新代码,查看master分支中模块二的文件,内容仍然是最初的,如下:

$ cat m2 test2 $ cat m22 test22 

我们可以使用同样的方法即可将b2分支合并到master分支中。既然是想将b2分支合并到master分支中,就需要先检出到master分支,但是由于我们当前就处于master分支,所以就不用执行checkout命令了,直接执行merge命令即可,不过,在执行merge命令之前,请先思考一个问题,在当前状态下,如果将b2分支合并到master分支,还能使用”Fast-forward”模式吗?

答案是:不能。

$ git merge b2 
$ git merge b2 Merge made by the 'recursive' strategy. m2 | 1 + m22 | 1 + 2 files changed, 2 insertions(+) 

从上图可以看出,当我们将b2分支合并到master分支以后,产生了一个新的提交,这个提交属于master分支,这个提交中包含了来自b2分支中的变更,这个提交的注释信息是”Merge branch b2″,正是刚才git默认生成的注释信息。

其实,我们每次执行git merge命令时,git都会先去尝试能不能使用”Fast-forward”的模式进行合并,如果能,就默认使用”Fast-forward”的模式进行合并,如果不能,就创建一个合并提交进行合并


现在,我们着重的看一下merge命令以及常用的一些参数。

git merge A 

上述命令表示将A分支合并到当前分支。

git merge --no-ff A 

将A分支合并到当前分支,但是明确指定不使用”Fast-forward”的模式进行合并。

git merge --ff-only A 

当能使用”Fast-forward”模式合并时,合并正常执行,当不能使用”Fast-forward”模式合并时,则不进行合并。

摘自朱双印老师博客http://www.zsythink.net/archives/3470

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/233518.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 什么是递归,通过这篇文章,让你彻底搞懂递归

    什么是递归,通过这篇文章,让你彻底搞懂递归想了解更多数据结构以及算法题 可以关注微信公众号 数据结构和算法 每天一题为你精彩解答 也可以扫描下面的二维码关注啥叫递归聊递归之前先看一下什么叫递归 递归 就是在运行的过程中调用自己 构成递归需具备的条件 1 子问题须与原始问题为同样的事 且更为简单 2 不能无限制地调用本身 须有个出口 化简为非递归状况处理 递归语言例子我们用 2 个故事来阐述一下什么叫递归 1 从前有座山 山里有座庙 庙里有个老和尚 正在给小和尚讲故事呢 故事是什么呢 从前有座山 山里有座庙 庙里有个老和尚 正

    2025年6月22日
    1
  • linux发起iscsi_iscsi自动连接

    linux发起iscsi_iscsi自动连接1、存储介质1)磁盘阵列:磁盘阵列是一种采用RAID技术、冗余技术和在线维护技术制造的一种高性能、高可用的磁盘存储设备。2)IP-SAN存储:SAN(StorageAreaNetwork-存储区域网络):是计算机信息处理技术中的一种架构,它将服务器和远程的计算机存储设备(如磁盘阵列、磁带库)连接起来,使得这些存储设备看起来就像是本地一样。SAN就理解成存储虚拟化,而IP-SAN就是采

    2022年8月23日
    5
  • centos系统服务优化SHELL脚本

    centos系统服务优化SHELL脚本

    2021年8月16日
    57
  • input debounce

    input debounce项目背景是一个搜索框,不能实时的监听onChange事件去发送请求,这样会造成服务器的压力解决思路就是用setTimeout+clearTimeout普通js代码如下:/下面是普通的js实现,可以参考一下//获取input元素vartextInput=document.getElementById(‘test-input’);//初始化一个…

    2022年6月20日
    57
  • shell编程中if语句_linux shell if语句

    shell编程中if语句_linux shell if语句read-n1-p”Let’sgo(yorn):”if[“$REPLY”x=”y”x-o”$REPLY”x=”Y”x];then#dosomethingfi①、注意空格。eg. if   [  $REPLY  =  “Y”  ]示例中为了看的明显,输入了连续的空格,写shell脚本时,只需一个空格即可

    2022年8月18日
    4
  • 数据结构:图结构的实现「建议收藏」

    数据结构:图结构的实现「建议收藏」图是一种很重要的数据结构,不解释。

    2022年6月28日
    29

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号