在git hub中将B合并为A与A合并为B之间的区别是什么

时间:2013-09-02 14:38:40

标签: git github

我开始通过使用git hub for Mac获得git hub的支持。我注意到merge branches选项允许你将一些分支,A合并到一些分支,B。你也可以用另一种方式,将分支B合并到一些分支A.有什么区别?我从git hub文档中找到了this,但它没有解释我想知道的内容。

enter image description here

3 个答案:

答案 0 :(得分:2)

值得添加的是,git的分支标签不会存储在提交中。

在进入休息之前,让我们在内部记下提交的内容。它是一个描述(以复杂的方式)整个工作树 1 的存储版本的条目,以及:

  • 作者和提交者(姓名和电子邮件地址)
  • 两个时间戳(作者和提交者,再次)
  • 零或更多"父提交"

"父母承诺"你是如何遵循一个分支的历史。 "定期"提交具有单个父级,即从中派生新工作树的先前提交。 "合并"提交至少有两个父母,一个" root"提交没有父母:它的树是从零开始的。

Git有很多方法可以命名任何单独的提交。 "真名"是SHA-1哈希,从问题中的图像中的9e17c4e开始。该名称永远不会改变,事实上,它是对提交的全部内容的加密强校验和。 2

但是,这些SHA-1值很难打字(如果我需要,我会尝试剪切和粘贴)。所以通常有另一种方式来引用提交。 Git提供"分支"和"标记"命名作为给他们一个有意义的名字的方式。 git branchgit tag命令可以创建一个新的"引用名称"对于现有提交。分支只是存储在refs/heads/中的引用(例如refs/heads/master),而标记是存储在refs/tags/中的引用。 (通过将这些引用存储在这样的目录层次结构中,git还允许在将来发明新类型的引用。实际上,refs/notes/commits已经使用了git notes,当然还有& #34;远程分支"存储在refs/remotes/。)

&#34;分支&#34;之间的主要(用户级)差异和#34;标签&#34;是一个标记假定是永久性的,而一个分支是假定移动。 refs/heads/中的分支 - 引用 - 当您在分支上时添加新提交时,会自动移动 <#34;&#34;。如果你告诉git进入分支B,然后向分支B添加新的提交,git进行新的提交,然后将分支标签移动到新的承诺。如果您愿意,可以将分支标签视为一种粘滞便笺,即git剥离并放置分支的新端/尖端。

这正是Cupcake illustrates。如果你在分行B&#34;&#34;并且你git merge A,合并将一个新的提交 3 添加到B-specific,一个&#34; merge commit&#34;,有两个父提交。然后,因为你在&#34; on&#34;在分支中,git将分支标签移动到新的提交。现在,名称B引用合并提交及其两个父项。

同样,如果您在分支Agit merge B上,则合并会添加新提交。它几乎完全相同的提交 - 事实上,它具有完全相同的树,当然还有相同的作者和提交者。如果你以某种方式设法做到这一点 - 在一个平行的宇宙中,也许: - ) - 在同一时间,它甚至有相同的时间戳。但还有另外一个区别。 虽然新提交将具有相同的两个父项,但它们将按其他顺序排列。当然,git将移动分支标签,但此时标签为A而非比B

父母的命令很重要。也许不是很多,而且对于普通的&#34;提交,只有一个父母,首先没有什么可订购的。但是它们会影响SHA-1校验和,它们也会影响父级遍历&#34;。当通过这个父提交链向后追踪一个分支时,git具有&#34;第一个父级&#34;的概念,并且各种命令采用标志--first-parent来限制父级跟随。

请记住,分支标签实际上只标记一个,单个,提交:分支顶端的一个。一组提交&#34; on&#34;通过跟随父母,根据需要动态导出该分支。在合并提交中,有多个父级,分支可以包含所有其父级 - 同时跟随所有父级 - 或者,对于简单情况,只需第一个家长。通过这种方式,您可以找到分支机构上的内容&#34;合并前#34;带来&#34;其他一些分支上的所有内容。

所以,这是为什么(以及 时)合并中的订单:当您想要查看&#34时;在分支机构&#34; &#34;前&#34;合并,你可以假设只有第一个父母才能得到你。

(虽然有一些皱纹。特别是,&#34;快进&#34;合并不会创建合并提交,它只是拉动分支标签&#34;转发&#34;。 ,由于分支标签完全是在密码校验和系统之外,任何人都可以随时重新标记任何分支,并且git repo中没有记录。在&#中有记录34; reflog&#34;,但是reflog条目会随着时间的推移而过期,并且可以被清除:它们意味着如果你不小心摔倒在地,帮助你解决问题,而不是为了防止你偷偷摸摸和混乱但是这已经太久了,我还没有达到我的脚注......)


1 从技术上讲,提交树会记录分段索引的内容。这就是为什么你git addgit rm的事情,把它们放在舞台上#34;并按照您喜欢的方式排列树,然后才git commit分段索引。

2 &#34;内容&#34;涉及到各部分的SHA-1校验和,因此这部分是校验和的校验和。我不是密码学家,但据我所知,这通常会降低加密强度。但是,它并不是为了安全。这些校验和是使git工作所必需的。如果两个不同的底层git对象(文件又名&#34; blob&#34;,树,注释标签和提交)总和相同,git将会中断。

3 这假设一个非常重要的&#34;合并不会导致&#34;快进&#34;。合并&#34;功能分支时会发生简单的合并。回到主要分支&#34;主分支没有工作:

A--B                master
    \
     C--D--E        feature

如果你只是git checkout master然后git merge feature,git会注意到master是&#34;直接祖先&#34; feature的{​​{1}},因为它可以从提交Efeature引用的提交)开始,然后向后工作并达到提交B(您提及的那个) #39;在&#34; on&#34;当你在分公司大师的时候#34;)。在这种情况下,git merge feature只会将标签剥离提交B并将其粘贴到提交E上。

强迫&#34;真实&#34;合并,你仍然git checkout master以便进入分支master,然后使用git merge --no-ff feature,与两个父母一起创建一个新的合并提交M

A--B---------M      master
    \       /
     C--D--E        feature

&#34;第一&#34;现在,您可以通过编写master^master~1来命名父级,即提交B。 &#34;第二&#34;现在,您可以通过编写master^2feature来命名父级,即提交E。请注意,master~2引用提交A:代字号在第一个父代之后。 (您可以使用稍微笨拙的Dmaster^2^命名提交master^2~1,依此类推。有关指定修订的更多方法,请参阅git rev-parse的文档。)< / p>

答案 1 :(得分:0)

如果将分支A合并到B中,则只有B的分支更新为新的子提交,而如果将分支B合并到A中,则只有A的分支更新为新的子提交。

这是图表形式的样子,从未合并的分支开始:

---o---o A
    \
     o B

现在让我们将分支A合并到B(带git merge A):

---o---o A
    \   \
     o---o B 

查看B如何更新为新的子提交,而A保持不变?

现在让我们看看如果我们通过将B合并为A(使用git merge B)来反过来会发生什么:

---o---o 
    \   \
     o---o A
     B

在这种情况下,A已更新为新的子提交,而B保持不变。从这里开始,您还可以将A合并到B中,这将使B快进以与A进行相同的提交:

---o---o 
    \   \
     o---o A, B

使用^修订说明符时,合并的顺序也可能会影响哪个父提交被认为是第1次到第2次:

  1. head^head^1都指代子提交的第一个父级。
  2. head^2指的是子提交的第二个父级。
  3. 但是,就提交图而言,合并的顺序没有区别,您仍然会得到一个指向两个父项的子提交。

答案 2 :(得分:0)

有区别。如果将A合并到B中,A将保持不变,B现在将从分支A进行更改。