4. git merge简介,以及git merge的参数–ff、–no-ff和–squash的区别?
1.git merge原理
A---B---C topic
/ \
D---E-----F------H master
在master分支中使用git merge topic,只会将C和H中的文件进行比较,如果没有冲突就会生成H。A、B、C都不会放进master分支中。
但是通过git log --oneline查看提交日志时,会发现A、B、C好像放进master中了,但是其实没有。为了证明这一点,我们可以在H处使用 git reset --hard HEAD^回到上一个版本,此时我们发现我们回到了F,而不是C。
虽然A、B、C都不会放进master分支中,但是分支的信息是保存的,即使topic指针被删除。
git merge --abort:当发生冲突以后,各个冲突会在readme.txt文件中显示,也就是说readme.txt被重写了。如果想要放弃这次合并,就可以通过git merge --abort。
参考:git merge 原理
git删除分支时究竟会删掉哪些东西
2.git merge的过程中,有文件发生冲突,会如何处理?
A---B---C topic
/ \
D---E-----F------H master
假设在master分支中使用git merge topic时,C和F中的readme.txt发生冲突。此时git会将冲突的内容放入工作区的readme.txt中,我们可以通过修改工作区的readme.txt文件来处理冲突。当工作区的readme.txt文件里存的是冲突的内容,那么就会出现如下红框中的标识:
自动将冲突的具体信息放在workspace中的readme.txt文件中,那如果工作区有readme.txt文件,那不就被覆盖了?
答:如果工作区对readme.txt文件的修改未提交到仓库中,那么会提示你去先进行add和commit或者stash。
冲突的具体信息放在workspace中的readme.txt文件中,那么readme.txt中是什么信息呢?
答:git会将C和F相对于E的修改分别在readme.txt中列出来。
git是按行对比两个冲突文件之间的差异。
3.git merge的参数–ff、–no-ff和–squash的区别?
根据官方文档可知,–ff和–no-ff是在“当合并的历史是当前历史的后代”的情况才起作用的,下面具体介绍一下什么是“当合并的历史是当前历史的后代”:
A---B---C topic
/ \
D---E-----------H master
上面我们可以看出:从E分叉出topic分支,topic分支上提交了A、B、C,但master上从E开始没有进行提交。
当我们处于master分支,想要将topic分支合并到master中时,就涉及到三个不同的选项–ff、–no-ff、–ff-only。也就是说这三个选项只在本情况有效,本情况为:master上从E开始都没有提交,并想要将topic分支合并到master中。这种情况称为“当合并的历史是当前历史的后代”。
节点的tag不存储在refs/tags/中时,默认使用–no-ff。其他情况默认使用–ff
–no-ff:创建新的提交H,得到如下结果:
A---B---C topic
/ \
D---E-----------H master
–ff:不创建新的提交H,将指针mater指向C,得到如下结果:
D---E---A---B---C master
–squash:将待合并分支的最后一个提交放到当前分支的工作区。如A、B、C对readme.txt进行了修改,那么–squash的作用就是将经过A、B、C修改的readme.txt文件复制到工作区中。然后我们就可以进行add和commit来生成一个提交。生成的这个提交,就相当于对A、B、C工作的总结。
如果复制到工作区的readme.txt文件与工作区中的readme.txt文件有冲突??答:出现这种冲突时的处理办法就是将冲突内容全部展示在readme.txt中。
–squash只是为让提交的日志看起来简洁一些。