结论
git merge 合并是按时间线合并在一起。会交叉合并。缺点:因为按时间线合并,所以和别的分支交叉后,看起来乱。 优点:应该是简单吧
git rebase 合并会把当前分支的 commit 放到公共分支的最后面,所以叫变基。优点:看起来干净,清楚。 缺点:相对麻烦一点。处理冲突的时候得一次次continue。
分析
如何验证这个过程:master分支上有一个a.js文件。基于master建立两个分支 test1,test2。 test1里面先修改。保证test1的时间点是最先的。
第一:merge的合并方式。
- 修改test1分支的a.js。添加一行 console.log('1').
git add .
git commit -m 'test1-1' - 切换test2分支。修改a.js.添加一行console.log('2').(跟test1分支是同一行,为了制造冲突)
git add .
git commit -m 'test2-2' - 我们说merge是按时间的。现在切换到test2。
git merge test1
解决冲突,然后提交。(git add . , git commit -m 'merge')再看分支图。
可以看到分支图开了分支。并且test1-1到了test2-2前面。如下图3: git merge test1; - 回到test1
git merge test2
分支图和合并后的test1是一样的。如图4: git merge test2 - 再验证反过来的情况。将test1,test2都回到最开始的 新建a.js 对应的commit id。然后重复1,2步骤。刚刚我们是讲test1合并到test2上。此时我们再验证将test2合并到test1上。 因为按照时间合并,所以分支图跟刚刚的是一样的。(我就不验证了)
注:回退的方式,我用的是Git reset --hard commitid编号
第二:rebase 的合并方式。
回到最初状态,1,2步骤跟上面是一样的。
- 修改test1分支的a.js。添加一行 console.log('1').
git add .
git commit -m 'test1-1' - 切换test2分支。修改a.js.添加一行console.log('2').(跟test1分支是同一行,为了制造冲突)
git add .
git commit -m 'test2-2' - 在test2分支上
git rebase test1
解决冲突,rebase的冲突是一个一个解决的。中间会有变基的过程。解决完一个
git add .
git rebase --continue
直到最后报成功.Successfully rebased and updated refs/heads/test2.(中间如果出来命令窗口,可以编辑。然后ESC,:wq。退出保存即可),冲突如下图5:git rebase 冲突;
解决完冲突,可以看一下分支图,如下:
(你可能会说,这不也是按时间来排的吗。其实不是。因为我们还没要试另一种情况。就是还重复1,2.然后把test2合并到test1上的情况。这里先记一下,是这个样子的。而且很明显的是就一条线。清晰。也没有因为冲突产生的merge那个commit)。
- OK,继续验证,还将test1,test2都回到最开始的 新建a.js 对应的commit id。然后重复1,2步骤。
- 在test1分支上
git rebase test2
如上面解决冲突
然后看分支图,如下:(是不是跟上面的不一样了)
图7
这就说明了最开始的总结:git rebase 合并会把当前分支的 commit 放到公共分支的最后面,也就是图的最上面。这样有个好处,如果test1分支上,还要改动仍然可以和此时的“test1-1”和为一个commit。(下面会说合并commit的情况)
工作规范
首先:每次开发一个模块,会有很多次commit。我们应该把一个功能的commit都归为一个commit。通过git rebase -i(下面会介绍如何合并commit)。这样保证当前是一个commit,看起来整洁,清晰。
切记:如果通过git rebase 合并分支,一定要将本分支的多次commit合并到一起。不然如果有冲突,会交叉比对。很麻烦处理。所以一定要合并一个功能的commit。
其次:每天都要拉一下master分支。这时,在自己的分支上。通过git rebase master. 合并主分支内容。保证本地代码是最新的。而此时通过rebase合并后,本地修改的commit位于最前面。接下来再修改的内容,还可以通过git rebase -i和之前自己修改的合并到一个commit。保证了此次功能仍然是一个commit。
最后:如果要上线发布。再一次合并master后,直接到master上合并本地的即可。
通过rebase的方式,可以做到让分支图就一条线。清晰明了。只要大家按照一定的规范,就会开发起来很方便。
git rebase的使用
一个功能中,提交了很多的commit,这时需要合并到一起。分两种:
一:这些commit都是本地的。
二:这些commit有的是本地的,有的是远程仓库。远程的一旦修改后,会提醒我们pull.直接push。是push 不上去的。 可以通过 git push -f. 这样直接就覆盖了远程的。但是前提再这个处理之前一定git pull 过。代码保证是一样的。
这两种只有push有点区别外。其他都是一样的。
git rebase合并多条commit记录
1.确定此次合并基于的base记录
git log 查看历史
假如此次功能提交了四次,那么参考的基准,应该为这四次的上一次。如果从上往下数的话,也就是第五次。获取这个的commit id
git rebase -i 对应的第五个的commit id
其实就是如下图中标记的commit id 。也可以通过git log查。
2.然后进入git内置的vim界面,此次功能的四次提交,前面都加上了pick。意思是这四次提交都会被采用,并显示在Git的提交记录中。这四次提交涉及的代码改动都是需要的,但是只需要一条提交记录,因此先按“i”键进入INSERT模式,将后三次commit id前面的“pick”字样改为“s”,只有第一次的commit id前面是“pick”,然后按ESC键退出编辑模式,并输入:wq进行保存。
3.去除多余的commit描述
在上一个pick与squash编辑界面用:wq保存后,会跳出最后的commit描述编辑界面,这里按“i”键进入INSERT模式后,可以把不需要的后三条commit描述用“#”号注释掉,只留下第一次提交时的描述,然后用ESC键退出编辑模式,再输入:wq进行保存。
提示成功后在查看分支图。只剩下了4。
路漫漫其修远兮,吾将上下而求索~~~~~