前言
利用git版本控制工具时,我们通常会从主分支拉出新分支进行开发,开发完成后创建pr(也就是pull request),让其他小伙伴帮忙review,确定代码没有问题后再将新分支合并到主分支上。但是,你真的理解pull request中比较的两个分支到底是谁吗?
下面以一个虚拟案例进行说明:假设主分支名为“Master”,拉出来的新分支名为“developBrance1”。
注:图中的箭头指代工作推进方向,而不是提交的指向(提交指向总是由当前提交指向父提交,和这里的箭头是反着的)
最简单的情况
上图中,我们从主分支Master的m1提交点拉出新分支developBranch1,然后在developBranch1分支上开发(开发过程中产生了d1、d2、d3共3个提交),开发完成后创建pr,然后经过Review后将其合并到主分支上形成新的提交点N。自然而然地,我们创建pr时选择的源和目标为:
src[developBranch1] -> dest[Master]
我们期望pr比较的是developBranch1和Master这两个分支的最新提交点,pr实际比较的也是developBranch1的d3提交点和Master分支的m1提交点之间的差异。
增加一点复杂度
假设现在有其他小伙伴和你一同工作(这才是工作中的场景),另外一名小伙伴也从Master分支的m1提交点拉出分支developBranch2进行开发,并产生了若干提交,而且在我们开发完成之前已经合并到了Master分支上:
现在我们创建pr时,源和目标自然还是:
src[developBranch1] -> dest[Master]
但此时pr实际比较的是developBranch1和Master这两个分支的最新提交点吗( developBranch1的d3提交点和Master分支的m2提交点)?
答案:不是的。现在pr比较的其实是developBranch1的d3提交点和Master分支的m1提交点,和上面最简单的情况完全没有差别!
其实pr的底层这样实现非常有道理:
我们创建pr时,两个分支比较的差异只是自己开发的内容。试想,如果合作开发情况下比较developBranch1的d3提交点和Master分支的m2提交点之间的差异,那我们会同时看到其他小伙伴的开发内容,你会想,这不是反应了“最新工作进度”吗?不就是多看一个小伙伴的代码吗?好,再试想如果同时有很多人开发,我们提交自己的代码时,夹杂了许多其他小伙伴的代码,你会不会因找不到自己开发的代码而发疯?
“最新工作进度”的疑惑还在吧?下面来解答。
git是如何反映最新工作进度的?
其实,git合并不同分支时,会自动取它们的并集,以保持最终工作进度。就拿上图说,如果developBranch1的d3提交点和developBranch2的o2提交点之间不存在冲突,两者的开发工作最终都会在m3中体现(当然,有冲突了就需要手动解决)。
现在还有一个问题,pr比较的原理是什么?
pr比较的是:
源分支的最近提交点和源分支和目标分支的最近公共父提交节点之间的差异。在文中第二张图中,可以看到源分支是developBranch1,目标分支是Master,两个分支的最近公共父提交节点是m1;所以最终比较的就是源分支的最近提交点d3和m1。
探索欲强的读者也可以试试把不同分支分别作为pr的源和目标,观察pr输出的差异,以加深印象。
后记
其他更为复杂的分支pr原理类似,只是需要结合更为复杂的合并策略进行分析。文中若有疏漏,欢迎指正补充。
好了,该去复习复习寻找两节点最近公共父节点的原理了^_^