Git标签指向已删除提交时会发生什么?

62

假设我按照以下步骤操作:

  1. 创建分支 X
  2. 创建标签 t(针对分支 X
  3. 推送
  4. 删除分支 X

标签 t 会发生什么?它只是悬浮在那里吗?还是被认为是垃圾?

我应该在删除分支本身之前删除指向该分支的所有标签吗?

参考资料

来自Git 基础 - 标签

Git 使用两种主要类型的标签:轻量级标签和附注标签。轻量级标签非常类似于不会改变的分支 - 它只是指向特定提交的指针。

3个回答

76

标签 t 发生了什么?

假设您从提交 E 创建分支 x,然后对该提交使用标签 t。例如:

                           x (branch)
                           |
                           V             
A-----B------C------D------E
                           ^
                           |
                           t (tag)

如果您删除分支x,则标签t不会受到影响。

git branch -D x

标���仍然指向提交E
A-----B------C------D------E
                           ^
                           |
                           t (tag)

它被认为是垃圾吗?

不是,因为提交仍然被标签 t 引用。

如果提交被删除了怎么办?

你不会删除提交。你删除指向提交的指针,如果提交不再被引用,Git 将在某一天进行垃圾回收(取决于你的配置)。

请参阅git gc

即使你删除了所有普通引用,如分支和标签,这些提交仍将在 reflog 中一段时间内被引用,你可以访问它们,例如重新创建分支、打标签或者挑选等等。

你可以使用git reflog查看 reflog。还要看一下 gc.reflogExpireUnreachablegc.reflogExpire


编辑

如果一些方式导致 Git 的对象数据库损坏。或者一个文件从 .git/objects 被删除(例如,您意外地使用文件浏览器或命令行命令删除了它),或者一个引用指向不存在的 Git 对象(如提交、树或 blob 对象),如果 Git 尝试访问这些对象,你将会得到错误信息。

下面是当 Git 尝试访问不存在的对象或引用不存在的对象时可能出现的错误列表。

  • commit

    fatal: Could not parse object '<ref-name>'.
    

    example:

    fatal: Could not parse object 'master'.
    
  • tree

    fatal: unable to read tree <tree-sha1>
    

    example:

    fatal: unable to read tree 13a3e0908e4f6fc7526056377673a5987e753fc8
    
  • blob

    error: unable to read sha1 file of <blob-name> (<blob-sha1>)
    

    example:

    error: unable to read sha1 file of test.txt (e69de29bb2d1d6434b8b29ae775ad8c2e48c5391)
    

请查看Git内部原理,以深入了解。


这是否意味着,如果我在稍后被删除的分支中标记了提交,我仍然可以使用标记引用它。例如,如果我将标记v1添加到分支x中,那么在删除x之后,标记v1仍然可用吗?(考虑旧版本的错误修复,当这些版本只是主提交上的标记时,没有针对每个版本的特定发布分支) - Smartskaft2
4
只要您不删除标签,提交仍然会被引用,因此不会被删除。如果您需要再次创建分支,则可以创建一个以标签提交为起点的分支,例如:git branch <branchname> v1 - René Link

7
我不是在回答问题中的特定场景,而是在回答标题中的问题:指向已删除提交的git标签会发生什么?
如果你设法删除了一个被标签引用的提交(不确定你如何做到这一点 - 参见René Link's answer),那么该标签将只是一个指向无效提交的指针(可以通过手动编辑.git/refs/tags下的标签进行测试)。
在这种情况下,git tag的输出将类似于以下内容:
$ git tag
error: refs/tags/v1.0 does not point to a valid object!
v1.1
...etc

结账也会产生错误:

$ git checkout v1.0
fatal: reference is not a tree: v1.0

因此,对于一个问题“引用了一个被删除的提交的git标签会发生什么?”的答案是... 没有任何变化。它将保留在那里,指向一个无效的引用,直到您使用git tag -d <tag>将其删除。

1
如果您想要检出指向已删除分支中提交的标签,那么该标签是否无效? - testing
1
@testing no。该答案讨论了OP所描述的假设情况。有关实际场景,请参见上面的Rene's答案 - 1615903
4
Renè的示例展示了一个提交上的标签,在分支被删除后仍然存在。如果标签在分支X的以下提交之一(未在示例中显示)上,又会怎样呢?那么这个标签是否指向从合并创建的提交呢?例如,如果您在某个功能分支上有标签,将该功能分支合并到主分支中,最后删除该功能分支。 - testing
6
删除一个分支并不会删除任何提交记录。只有那些没有被标签、其他分支或引用所指向的提交记录才会被删除,并且仅在垃圾收集运行后才会删除。 - 1615903

2

请看我的编辑:标签非常类似于不会改变的分支 - 它只是指向特定提交的指针。如果提交被删除了呢? - idanshmu
2
你如何“删除”一个提交?假设你在主分支上,并且已经用“1.0”标记了你的主分支,现在你想要回滚最近的两个提交。你可以运行“git reset --hard HEAD~2”,这将使你的HEAD回到两个提交之前,从而使这些提交从你的主分支中“消失”。但是它们仍然存储在你的repo中,只是不在主分支中。你的标签“1.0”仍然指向正确的提交,不会有任何问题。 - Jacob Nelson
1
或者按照你的情况,如果你只在一个分支中提交了代码,然后删除了该分支,这些提交记录并不会被移除。如果你在删除该分支后使用'git reflog'命令,你仍然能够找到这个分支上的commit SHA1值,这也是标签所指向的内容。 - Jacob Nelson

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