Git标签是否会被合并?

22
假设我们正在使用git和拉取请求进行开发,并且我们有:
1. 主分支 2. 一个 release/1.... 分支 对于每个热修复或功能,也有一个分支,在拉取请求被接受后合并到起始分支中。
所以我的问题是: 1. 如果发布分支包含标签,并且在 release/1.x.y 的最后一个发布版本之后将发布分支合并到主分支中,那么标签是否也会被合并? 2. 长期支持的问题是: 假设有人想在10年后检查标签1.1.1的状态。如果发布分支已被删除但已合并到主分支并且我们有主分支,是否可以检出此标记的提交?
谢谢

enter image description here

4个回答

19
你标题中的问题“git tag是否合并?”的字面回答是“不”,但这并不是一个有趣的答案,因为分支名称也一样不是。在Git中,合并是通过提交来完成的。你发布的图表还不错,但其中有一些误导性的地方。以下是一些关于它的注释:箭头指向前面。Git不会往前工作,Git是往后工作的。圆形代表提交。一些提交是合并提交,而另一些则是普通提交。分支和标签名称只是标识一个提交。标签名称与分支名称的主要区别在于分支名称随着时间的推移而移动,这意味着它始终指向最新的提交。
A <-B <-C   <--master

名称master指向最后一次提交,C。提交C本身指向较早的提交B,它又指向第一次提交A。(因为A是第一次提交,所以它不会指向任何地方,这就是Git停止遍历的方式。)

要添加一个新的提交 - 让我们称其为D - Git将新提交写出,以便它指向现有提交C,而C曾经是分支上的最后一次提交。然后Git将D的实际哈希ID(无论是什么)写入名称master中:

A <-B <-C <-D   <--master
如果将标签名称指向其中一个提交,则该标签名称保持不变。
A <-B <-C <-D   <--master
            ^
            |
         tag:v11
当我们添加一些新的提交时,我们得到:
A <-B <-C <-D <-E <-F   <--master
            ^
            |
         tag:v11

标签名称没有变动过,并且永远不应该改变。(您可以手动“移动”一个标签,方法是删除它并创建具有相同名称的另一个标签,或使用其中一种强制选项,但一般情况下不应这样做。)

如果发布分支被删除,是否仍然可以检出此标记的提交记录...

当然可以。分支名称、标签名称和其他名称用于定位一个特定的提交记录。您可以使用该名称直接转到该提交记录。只要名称本身继续存在,该提交本身将在Git存储库中保留。

找到某个提交记录(通常通过名称),Git可以使用嵌入在每个提交记录中的内部箭头向后移动历史记录。这意味着如果有一个提交记录 D 的名称,就像上面的示例图中一样,Git 可以使用 D 找到 C,从而找到 B,再找到 A。因此,这四个提交将始终保留在此存储库中,因为可以找到 D

请注意,名称 master 定位到提交记录 F,这意味着提交记录 F 被保留。提交记录 F 定位到提交记录 E,后者又定位到 D,以此类推;因此,这些提交也将被保留。因此,有两个名称意味着必须保留 D 及更早的提交记录。如果删除其中任何一个名称,则 D 保留名称的数量将减少为1,但是仍然必须保留 D。不过,如果我们删除的名称是 master,那么提交记录 F 就不再需要保留了。如果丢弃提交记录 F,那么表示提交记录 E 也无法找到,因此提交记录 E 也可以被删除。

如果我们添加另一个名称以查找提交记录 F,则在某种意义上,删除名称 master 就变得安全了。删除名称 master 将实际上“遗忘”了 master 中的最后一个提交,在此时,它是提交记录 F,但是提交记录 F 将通过其他某些名称找到,因此不会被删除。

请注意,任何合并提交都有两个(或多个1)箭头从中出来。如果可以找到该合并提交,则从它出来的箭头会保留沿着每个路径向下的所有较早的提交记录。因此,一旦您将某些分支端提交(由某些分支名称标识)合并到要保留其名称的其他分支中,即可安全删除已合并分支的名称:您将无法直接找到该末端提交记录,但是可以通过找到具有其作为其中一个额外父提交记录哈希 ID 的 合并提交 找到它。


1Git 将这种具有多于两个“腿”出来的合并称为章鱼合并(octopus merge)。这可能就是为什么 GitHub 使用


讲解得非常清楚! - eRunner

7
1.) 如果发布分支包含标签,并且在release/1.x.y的最后发行版本之后将发布分支合并到主分支中,那么标签也会被合并吗? 回答: 不会合并标签,只会合并提交(无论是否打上标签)。
2.) 至于长期支持,我的问题是:假设有人想要在10年后查看1.1.1标签的状态,如果发布分支已被删除,但已合并到主分支并且我们具有主分支,是否可以检出此标记的提交? 回答: 是的,这不仅是可能的,而且是标签的根本目的。 标签是特定提交的永久引用,因此即使它们未合并到任何内容中,这些提交也将保持可访问性,以供以后进行检查。

1
这不是个悖论吗?我没有标记提交的分支,而且标记也没有合并到主分支,但是10年后我仍然可以检出该标记。 - user1911091
3
一个悖论?为什么?这就是标签的目的:在某些状态上放置一个不可移动的参考。另一方面,分支会来了又去。如果一个提交既没有被标签引用,也没有被分支引用,它将变得符合垃圾收集的要求。但是标签可以防止这种情况的发生。 - Romain Valeri
这也是我的理解,但不知何故,AVH git-flow正在创建带有消息 Merge Tag '1.x.y' 的提交记录,我不明白为什么除了 Merge branch 'hotfix/1.x.y' into master 之外还需要它。有人知道为什么会创建这些看似多余的提交记录吗? - avatarofhope2

3

答案是正确的,但有点复杂。以下是简短的回答:

如果发布分支包含标签,并且在 release/1.x.y 的最后一个发布版本之后将发布分支合并到主干中,那么标签也会被合并吗?

标签与分支关系不大,它们只指向特定的提交 - 不管提交在哪个分支中。
所以,是的,在合并后标签仍然可用。

对于长期支持,我的问题是:

假设十年后有人想检出标记1.1.1的状态。如果删除了发布分支但已将其合并到主分支中,我们有主分支,能否检出此标记的提交?

可以。


1
它们只指向一个特定的提交。就像分支一样。标签和分支并没有太大的区别。标签基本上就是不可移动的分支。 - undefined

2
如果您只是将开发分支合并到主分支,那么您不会失去标签。标签和分支之间的区别在于,标签是特定提交的标记(标签不随下一次提交而移动。相反,分支随每次提交而移动)。因此,如果您进行合并操作,并且将带有标签的提交推送,您可以返回到具有标签/标记的提交。
您只需要记住将标签推送到远程存储库即可。示例合并带有标签的分支

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接