Git合并模式

  在使用Git进行分支合并和提交时,会出现一个短语“fast-forward", 一个人的小仓库倒是没什么,但是要牵扯到团队合作提交时就会有一些意思。

  实质上合并分支时有里那个模式,即 fast-forward 和 non fast-forward。在我们合并分支时,希望看到的(我希望看到的)经常是:在合并分支后,使用 git log --graph --pretty=oneline 查询分支合并情况,会出现很清晰的分支的”分离“ 和 ”合并“ 轨迹。不过有时有就算我合并了分支,却不会出现这样的”轨迹“,合并完成后的主分支(以下举例master为主分支,dev 为支线分支)仍然想没用分支合并一样。这就牵扯到了上述两个合并模式的概念。

Fast-forward

  当我使用master一路add+commit 提交时,突然有了一个有意思的想法,我需要测试这个想法,同时我又希望在我测试过程中保证原有的master提交不变,直到我想要将这个新电子加入主要功能为止。Git为此提供了”分支“功能,我很高兴。于是,我创建了一个分支dev,并切换到dev分支。随后我在dev分支上修改原有的文件或者加入新的文件。在一阵瞎J8改后,我觉得这一切都是天意,我注定是要把这些神迹加入已有的稳定版本,让我的小项目更加犀利。在保证我已经在dev分支将我的修改提交到版本库的dev分支上后,我切换回了master分支。原有的知识令我自信的知道master此事仍然处于之前创建dev分支时的稳定状态,所以我在master分支上行云流水地打出了几个单词:

[master]>git merge dev

Updating 72f5881...9938f54

Fast-forward

Text.txt | 1 +

1 file changed, 1 instertion(+)

提示告诉我已经合并完毕,不过有一个Fast-forward的句子,我并没有在意。随后我使用一招 git log --graph --pretty=oneline, 长长的参数照耀着我的弱鸡虚荣心,我敲入回车后充满期待地想看到这两个分支分分合合的绚丽符号。但是,现实全是和我用一个分支时几乎相同,不同的就是因为我的--graph参数是的每个commit id前面有一个*代表每次提交的轨迹。

  上面这么多中国字,我想说的就是,当创建分支dev后,只对分支dev修改而没有在master分支上进行任何commit,那么当再切换回master分支,并将dev分支合并到master分支时,默认方式就会使用Fast-forward模式合并,即在保证没有冲突的情况下,Git会移动dev分支上commit的文件指针,使这个commit移动到master分支上来。上面这一句的意思是从http://my.oschina.net/yuzn/blog/82297?p=1上讲的。但我的理解有些分歧,我不认为是 “移动”, 因为在Fast-forward模式合并分支后,master和dev分支上最新的commit id 是完全一样的。所以我的理解是 ”复制“,即这种模式复制了文件指针给master分支,因为复制的是文件指针而不是commit的具体内容,所以这样更快,故名Fast-forward。这样的结果就是合并之后的master不会保存合并的dev分支的修改记录,看起来就是”扁平状“的,和单分支提交一样。

non Fast-forward

  当在master创建分支dev后,在这两个分支上都做了commit(很重要!注意是在有了dev后的过程中对master进行了修改并commit),之后的分支合并就会使non fast-forward模式。这个模式就是那种可见的,用git log --graph能看出分支轨迹的模式。这种模式的合并会让master分支记录dev分支的开发记录。细一点说,这样的模式不是简单的复制文件指针给master分支,而是在master分支上新提交一个commit,并在没有冲突的情况下将dev分支中的commit的内容复制给master上的这个新的commit,随后这个commit会记录之前dev上commit的记录,所以这时在master上就可以看到分支的修改合并轨迹。证明这一点的方法就是分别在master和dev分支上用git log 指令,可以看到合并后master分支最新的commit id 和 dev 上最新的 commit id 是不同的,这正是因为non fast-forward 合并是先在被合并分支上新建了一个commit。

  对于开发来说,自然是希望随时能看到合并的记录,以便之后分析项目。但之所以像我这样的弱鸡除非因此遇到麻烦否则不会注意以上两个合并模式,就是因为fast-forward 模式只能在master一直没有commit而只是合并dev时才会出现。在做自己的小项目是时,因为没有合理的开发流程,经常是在master和dev这两个分支上都会有文件改动。而只要是master分支在存在有其他分支时,对其进行了commit,那么以后的在master分支上的所有合并操作都会变为non fast-forward 模式。并且除非显示地使用non fast-forward模式,在默认已经是non fast-forward模式时使用合并操作不会让你在合并是输入新commit的注释(上一段说到non fast-forward 模式合并实质上是在主分支上新加了一个commit,但在单独新加commit时,会默认需要输入提交注释,而无注释的commit需要输入较长的参数),而是将dev分支上commit的注释直接复制到master上的commit。所以这样会不是很容易让新手注意。

  比较规范的Git分支管理策略是如http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/0013758410364457b9e3d821f4244beb0fd69c61a185ae0000上所说的,master分支只需要合并,而最新的测试研发版本都放在dev分支上,其他开发者的分支都与dev分支合并,dev分支唯一地向master分支合并。在这种流程下,master分支的合并应该就一直默认为fast-forward模式,这样也很合理,因为master分支发放的基本都是稳定版,稳定版不需要显示开发的分支轨迹,当然如果需要用non fast-forward模式合并分支也可以,这时候就需要输入一些显示的参数,具体为:

git merge --no-ff -m "commens" dev

其中 no--ff参数就是禁用fast-forward模式,而使用non fast-forward模式。因为是显式的non fast-forward合并,所以Git就显式的很彻底,需要开发者在加入参数 m 并输入新commit 的注释 ”comments"。最后的dev就是向master分支和并的分支。

 

posted @ 2016-01-23 18:58  J_Rui  阅读(774)  评论(0编辑  收藏  举报