平时在工作中,遇到过同事的代码被合并到了master分支但是我们并没有review过的情况,而且我看过提交历史后还是没有追溯并还原他当时是怎么操作的。因此我学习并研究了一下git的这个分支树图,特此记录。
看到上面的图的时候,你知道发生了什么么?如果你能够看懂,你就会清晰的知道代码的演进过程。有时候我们看到一段代码但是想不到它是如何在何时由哪个分支让谁合并进来的。学会阅读这个分支树算是一个额外的技能吧,虽然平时用的不多。
比如上面的分支树就表明,chenshang 在13分钟之前,从master
切出来了一个分支进行开发,在上面做了两个修改并提交,与此同时他又去master
分支做了一些修改并提交,最后在3分钟之前,他又把切分出来的的分支合并到了master
上,然后又从master
分支切分出来了两个分支,一个叫 feature/3
,一个叫feature/two
,然后`feature/two上还有一个提交。
什么时候会有分叉
当我们从master新建一个分支的时候,此时的新分支和 master分支是处于同一个起点,例如上图中的 feature/3 分支,一旦我们开始在分支上提交,那么这个分支的树就开始生长,也就是开始超前master分支了,例如上图中的 feature/two 分支,此时还没有开始分叉。一旦两个分支对应的公共父节点下的分支开始有提交,例如我们在feature/3 分支上做一个提交,那么分叉就开始了,就会变成下面图的情况。
注意:下图框起来的部分虽然是直线,但是他不是master的那条线,而是刚刚从master切出来的 feature/3 分支
为了让master 也产生一个分叉,我只需要回到master分支在做一个提交即可,如下可以看到master和其他两个分支开始产生了分叉。
注意,此时的这条绿线才代表master分支,跟刚才的那条已经不一样了。
我把 feature/3 分支往 feature/two 分支上合并,可以看到一个聚合的提交节点,A minute ago
两个分支合并了。
然后我把feature/3分支删除,模拟工作中我们最常见的一个场景:分支功能开发完成并且已经合并到另一个分支(可能是master,也可能是另一个功能分支),当前分支就没用了,于是就可以删除了。 如下,我使用 git branch -D
命令把 feature/3 给删掉了
可以看到表征分支的标签不见了
可以看出合并轨迹
接下来继续吧feature/2分支合并到master分支
什么时候合并不产生一个节点
有一种场景,我们本地往master合并的时候不会产生一个合并的提交,而是跟直接在master分支上提交的一样。这种情况,出现在从一个分支切分出另一个功能分支进行了一些改动,此时原分支上并没有任何的提交,只要把功能分支往原来的分支上合并,默认情况下就是直接合并不会产生一个合并节点。
有一种场景,我们本地往master合并的时候不会产生一个合并的提交节点,而是跟直接在master分支上提交的一样。这种情况,出现在从一个分支切分出另一个功能分支进行了一些改动,但是原分支上并没有任何的提交,这时只要把功能分支往原来的分支上合并,默认情况下就是直接合并不会产生一个合并节点。 git中这种情况叫法 fast forward。
我们来看下,如下,我先准备:5 miniuts ago 我重新创建了 feture/3 分支,然后切换到master做了一个提交,然后又创建了一个feature/4 并做了一个提交。
注意这时候我把feature/4往master合并
合并完之后
没有一个新的合并节点,因为在master分支上没有任何提交,此时merge不会产生一个合并提交的节点。看上去就好像在master分支上提交的一样。如果出现这种场景,并不代表没有切换分支进行代码编写,有可能切换分支后往master分之合并的时候没有关闭 fast forward。但是这种情况一定表明是从本地合并了分支,而不是通过gitlab进行代码review后进行的合并。理论上通过gitlab合并一定会生成一个新的合并提交节点。
这个场景下,我么合并分支的时候看到如下提示。
而如果我们想要强制产生一个合并提交节点,只需要在git merge的时候加上 --no-ff 参数,关闭 fast forward即可。两个的区别如下
还有,此时如果删除分支的话
其实我们是看不出来合并的分支信息了就。
所以,如果我们使用gitlab的话最好这个开启下面这个配置,所有通过gitlab发起的合并请求都会产生一个合并的commit
执行如下命令。git merge 的时候加上一个 --no-ff 参数
则会生成一个合并
我么往master分支合并的时候就用这个,其他分支之间的合并的时候就无所谓了。
这样就能看出来一个合并了
下面这个场景也比较常见
git 配置默认不启用 fast-forward
Git 配置默认不使用 fast-forward 合并,可以通过设置 merge.ff 配置项为 false 来实现。以下是如何设置的命令:
git config --global merge.ff false
这条命令会全局设置 Git,使得在合并分支时,即使可以进行快进式合并(fast-forward merge),也会创建一个新的合并提交。
如果你只想对当前仓库进行设置,可以去掉 --global 选项:
git config merge.ff false
请注意,这种设置会使合并操作默认总是创建一个新的提交,即使合并可以通过修改指针完成“快进式”合并。