合并提交第一和第二父母

时间:2018-05-20 06:00:09

标签: git merge git-log

在一篇涵盖相对提交引用的Udacity课程中,它说:

  

^表示父提交,〜表示第一个父提交

     

^和〜之间的主要区别在于提交时   从合并创建。合并提交有两个父母。合并   commit,^引用用于表示第一个父级   提交,而^ 2表示第二个父级。第一个父母是   你运行git merge时你所在的分支,而第二个父代是   合并的分支。

基于命令行上运行git log --oneline --graph的以下输出:

graph

使用SHA f69811c的提交相对于(最顶部,带头指针)commit 9ec05ca是HEAD~4 ^ 2。合并提交1a56a81的第二个父级是f69811c,课程解释了这个“HEAD~4引用当前的第四个父提交,然后^ 2告诉我们它是第二个父级合并提交(合并提交)。“

根据黄色引用的课程文本,似乎e014d911a56a81的第一个父级,因为它是与合并提交具有相同分支的父级。

根据这些信息,e6c65a61a56a81的关系是什么?

我不认为它也是第二个父母(如果可以有多个第一和第二父母......),即使它也是合并为主人的分支,因为该答案在课程测验中被拒绝

另外,如果我e014d911a56a81的第一个父母,我是对的,20975213772ab11a56a81的关系是什么(如果合并提交实际上可以有多个父母,那么他们似乎也是第一个父母了吗?

2 个答案:

答案 0 :(得分:3)

我认为查看图表的一些替代演示可能会有所帮助。

考虑这个非常简单的菱形图,后来的提交被提取得更高,而早期的提交被提取得更低:

  D
 / \
B   C
 \ /
  A

在这里,D可能是合并提交的极短缩短的哈希ID,BC是它的两个输入(两个父项,用Git的术语)。 ABC的(单个)父级。因此,BC siblings,或者如果Git直接使用了这个概念:两者都有相同的父级,所以他们必须是兄弟姐妹(或者两兄弟或两姐妹或其他什么)。但是Git通常不会以这种方式谈论提交 - 它通常只对直接的父母/子女关系感兴趣。

我们可以 - 而git log --graph也可以这样做:

*    d...... fourth message
|\
| *  c...... third message
* |  b...... another message
|/
*  a...... some commit message

像人类孩子一样,Git"孩子"可以有多个父母。但是,最典型的情况是只有一个父级,在这种情况下,父级是第一个,最后一个,也是唯一的父级。您可以对其进行编号 - 例如C^1A,但并不存在实际需要。没有C^2并且要求它只会让你出错。

在StackOverflow帖子中,我喜欢使用 left 的早期提交和右边的早期提交绘制我的图形,如下所示:

  B
 / \
A   D   <-- master (HEAD)
 \ /
  C   <-- develop

这使我有空间插入分支名称,并将单词HEAD附加到其中一个,就像Git通常那样。但是,这使得很难分辨出哪一个是第一个,哪个是第二个。请注意,上面的第一个垂直图表存在同样的问题。

任何使用至少两个父项的提交称为合并提交。这使用单词 merge 作为形容词,修改 commit 。我们还经常将其视为合并,使用单词 merge 作为名词。正如ElpieKay所说,合并提交可以有两个以上的父母,但是这些章鱼合并(正如Git所说的那样)不做任何你只能成对合并做的事情,所以他们大多只是为了炫耀。 :-)当您与三个或更多父母合并时,您可以对所有父母进行编号。然而,Git本身唯一的特殊区别是第一个父级,使用--first-parent标志来使用各种Git命令,例如git log

令人困惑的是,git merge命令不必进行合并提交。它有两部分,我喜欢将 merge作为动词 - 将工作结合起来然后随后进行提交。它所做的提交是一个合并提交,除非你告诉它不要。并且,好像这已经不够混淆了,几个额外的Git命令将合并为动词部分,而不会产生合并提交。因此,记住动词形式,合并以及名词或形容词形式之间的区别非常重要。

值得注意的是:

  • 所有提交 - 所有Git对象,实际上都是只读的。一旦提交,它就永远不会被更改,因为它的哈希ID - 它的真实名称 - 通过哈希函数运行它的所有底层数据来计算。如果你以某种方式改变提交中的一个位,你就会获得一个新的不同的哈希值,从而得到一个新的不同的提交。

  • 由于父母或父母在孩子出生时存在,孩子可以记录父母。

  • 但是,由于父母的孩子在制作父母时尚不存在,所以父母不能记录其子女。

  • 这些反向构成提交图的父&lt; - child 链接。 1

这意味着Git的内部链接总是向后。 Git 必须 last 开始,最多孩子,提交并向后工作。这就是为什么分支名称master总是指向分支的提示的原因。随着Git向后工作,一次提交一次,合并 - 有两个或更多父母 - 提出一个问题:Git只能从孩子回到父母的一个。 Git解决这个问题的常用方法是将父项的所有放入队列,然后处理队列中的第一次提交。

--first-parent标志告诉Git只将第一个父项放入队列,忽略第二个父项(如果这是章鱼合并,则忽略任何其他父项)。这允许Git在没有一次提交多个提交的情况下遍历提交图。

1 在数学上,任何图形 G 都由顶点 V 和边 E 的集合定义,其中我们写为 G =(V,E)。图形可以是定向的,而Git是:从顶点到顶点的链接只有一种方式。这些边称为 arcs 。在我们的例子中,我更喜欢调用顶点节点; 这些是实际的提交本身,每个节点都包含所有传出弧的列表,即父提交的哈希ID。

Git的提交图不仅定向而且非循环,这意味着如果我们从任何一个提交开始,并遍历图表,我们&# 39; ll永远不会返回同一个提交。换句话说,没有父母可以成为自己的孩子。这是Git所做的各种图形转换的有用且重要的属性,因此我们有时会将Git提交图作为 DAG 进行讨论,它是 Directed Acyclic Graph 的缩写。 。提交图或提交DAG代表您所创建的所有快照。

请注意,每个源快照只是附加到一个提交。图表操作不必关心相应快照中的内容:它们只查看图表本身!

答案 1 :(得分:2)

e6c65a6是1a56a81的第二位父母(f69811c)的第一位父母。

3772ab1是1a56a81的第一位父母(e014d91)的第一位父母(2097521)的第一位父母。

提交可以为零父级。这是一个根提交。

提交可以有2个父项,这是以“真正合并”的方式将一个分支合并到另一个分支的结果。

提交可以有两个以上的父项,这是通过“章鱼合并”的方式将两个或多个分支同时合并到一个分支的结果。

要找出提交X的父提交,您可以使用:

S.no      Name                     Expected Result
------    ----------------------   ----------------------
1         2341 blvd                2341 Boulevard
2         648 s Kingston rd        648 S Kingston Road
3         sw Beverly st            SW Beverly Street

git log -1 X --pretty=%P

git log -1 X --pretty=raw