下面介绍了merge操作中为什么会出现parent1和parent2的分叉以及执行git reset --hard commit_id操作为什么会导致版本丢失和回滚不干净的情况。
1.f_test1和f_test2分支分别修改了不同的文件,都往master上merge代码
1) 创建f_test1\f_test2分支
git checkout -b f_test1 master
git push
对本地分支f_test1与远程分支进行关联:
git branch --set-upstream-to=origin/f_test1 f_test1
创建f_test2分支类似;
2) 在分支f_test1上创建3个文件a\b\c,分别往里面添加内容;
3) 在分支f_test2上创建3个文件d\e\f,分别往里面添加内容;
4) f_test1和f_test2分支merge到master分支
5) 查看日志
从提交日志里面可以看到
f_test1的merge操作没有在日志里面打印出来,原因是此时还只是往master上进行单线合并,分支没有进行分叉。
同时,合并时出现了“Fastforward”的提示。由于当前 master 分支所在的提交对象是要并入的 f_test1分支的直接上游,Git 只需把 master 分支指针直接右移。换句话说,如果顺着一个分支走下去可以到达另一个分支的话,那么 Git 在合并两者时,只会简单地把指针右移,因为这种单线的历史分支不存在任何需要解决的分歧,所以这种合并过程可以称为快进(Fastforward)
f_test2的merge操作在日志中打印出来了,
这次合并操作的底层实现,并不同于之前 f_test1 的并入方式。因为这次你的开发历史是从更早的地方c1开始分叉的。由于当前 master 分支所指向的提交对象并不是 f_test2分支的直接祖先,Git 不得不进行一些额外处理。就此例而言,Git 会用两个分支的末端(C3 和 C2)以及它们的共同祖先(C1)进行一次简单的三方合并计算。下图标出了 Git 用于合并的三个提交对象:
图1-5-2
这次,Git 没有简单地把分支指针右移,而是对三方合并后的结果重新做一个新的快照,并自动创建一个指向它的提交对象(C4)(见上图)。这个提交对象比较特殊,它有两个祖先(C2和 C3)。
6) 我们看看执行reset回滚会出现什么现象
回滚到merge f_test2的时候;
现在我们看看日志:
从日志里面可以看见。Merge f_test1的操作不见了,a\b\c.txt三个文件不见了,我们再回过头去看一下合并的详细过程
git merge f_test1执行完之后,日志的显示情况:
在本地工作目录D:\editiontest\git_demo下也增加了a\b\c.txt三个文件
git merge f_test2执行完之后,日志的显示情况:
从日志里面看,是多了2条纪录而不是多了一条记录,
当我们再看图1-5-2,可以明白,master的头指针回到了c3,会把c2和c4对象全部都给丢掉,c4是三方合并操作,c2是f_test1的提交内容,但是c3的内容仍然还在,所以对于回滚分叉的提交时,一定要谨慎,说不好就把不该回滚掉的代码给回滚掉,而想要回滚的内容却还在,这也是采用reset回滚不干净的原因所在;