压缩提交的标签会发生什么?

27

如果我有一个带有标签(例如tag-A)的提交A,然后下一个提交B带有标签tag-B;如果我合并这两个提交,那么这些标签会怎样处理呢?它们都会被分配给合并后的提交吗?

3个回答

20
标签不会移动,因为rebase会重写历史记录。原始提交将会有标签,因为标签不会移动。这是一张图片:

之前:

(HEAD) B - tag-B
       |
       A - tag-A
       |
       X

之后:

         B - tag-B
         |
(HEAD) C A - tag-A
       |/
       X

这里CAB的压缩。它开始一个全新的历史,AB将不再参与其中。分支头将移至C并从那里继续。


啊,所以提交 A 和 B 仍然作为“匿名”分支存在? - Jim
1
@Jim。基本上,提交是不可变的。一旦你提交了,唯一能做的就是删除它。标签是静态标签。它们不会移动,并与提交关联一个名称和可能的一些元数据。分支类似,但当它们被检出并提交时会移动。因此,在rebase期间,分支标签会移动,但标签和先前的历史记录不会移动。您可以手动将标签移动到新历史记录的某个位置,但完全由您决定如何以有意义的方式进行操作。 - Mad Physicist
迁移标签的最佳实践是什么?我们有经常压缩分支提交的 go 项目。Go 模块使用标签来拉取特定的包版本(即使它们不在主分支上)。我的担忧是,在删除旧分支时,任何标签都将变成孤立的(因为它们的提交会消失),并且会破坏后续的构建。 - colm.anseo
@colm.anseo。我不知道最佳实践是什么。任何合理的方法都应该可行。Git提交是不可变的,不会神奇地消失。我相当确定,如果你在图表上有一个标签,那部分是安全的。我不认为标签可以神奇地消失。 - Mad Physicist
如果我有以下内容:主构建引用分支B上的标签T;合并分支B;(构建仍将工作,因为标签T仍然有效);删除分支B(因为它已与主分支合并);标签T现在将成为孤立的(因为提交已经消失)?未来的构建将会失败。我将创建一个测试go项目来确认我的最终假设是否正确。 - colm.anseo
@colm.anseo。提交并没有消失。删除一个分支就像在Python中删除一个变量:你只是删除了对象的一个可能名称。提交本身仍然存在。 - Mad Physicist

7

这两个标签会被指向压缩后的提交吗?

不会。

每个标签都指向一个特定的提交,它不会自行移动离开该提交。每个标签所指向的提交仍然存在,只是没有在任何分支中。

压缩两个提交会创建一个单独的新提交,只包含原始提交的内容。这个新提交将不会有任何标签指向它。


您可以手动将这两个标签移动到指向您的新提交:

git tag -f tag-A
git tag -f tag-B

2

我认为Mad Physicist的回答很好,但我的好奇心驱使我想要自己重现这个过程以查看历史记录。以下是一个示例,您可以在本地重新创建它以查看历史记录。

首先,我们需要创建一个空白存储库:

cd ~
mkdir test_repo
cd test_repo
git init
touch file.txt
git add .
git commit -m "Create initial file"

然后我们需要创建一个具有多个提交的分支,并将它们压缩成一个:

git checkout -b new_feature
echo "A" > file.txt
git add .
git commit -m "Added A"
git tag tag-A

echo "B" > file.txt
git add .
git commit -m "Added B"
git tag tag-B

这让我留下了以下历史记录:
$ git log

commit 203a767647c3ebfc85b983dd573419013388b5aa (HEAD -> new_feature, tag: tag-B)
Author: Joshua Correia
Date:   Thu Jun 16 12:06:20 2022 -0700

    Added B

commit f16a24ae7b43110c98ee9a818db2a9f2ad5c8f3a (tag: tag-A)
Author: Joshua Correia
Date:   Thu Jun 16 12:06:09 2022 -0700

    Added A

commit a601965cd293c91820af6d9bc9bd9aa8965854a1 (master)
Author: Joshua Correia
Date:   Thu Jun 16 12:05:57 2022 -0700

    Create initial file

现在我们可以压缩提交并分析发生了什么:
git rebase -i a601965cd293c91820af6d9bc9bd9aa8965854a1

将第二行包含“Added B”的提交中的“pick”更改为“squash”,然后保存文件。

当我们再次查看历史记录时,会发现标签不再存在于此分支的历史记录中。这是因为标签与单个提交相关联,而这些提交已被我们的变基替换。请注意,由于创建了一个新提交来替换之前的两个提交,因此HEAD的哈希值现在已更改:

$ git log

commit 414d3cf4a12a3df293047de5271080d030cce119 (HEAD -> new_feature)
Author: Joshua Correia
Date:   Thu Jun 16 12:06:09 2022 -0700

    Added A

    Added B

commit a601965cd293c91820af6d9bc9bd9aa8965854a1 (master)
Author: Joshua Correia
Date:   Thu Jun 16 12:05:57 2022 -0700

    Create initial file

然而,这些提交并没有完全删除。如果你运行git tag命令,你会看到tag-Atag-B仍然存在。你可以使用git checkout tag-B命令查看在创建该标签时存在的历史记录,但这将使你处于分离头状态。


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