摘自朱双印老师博客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