指向已删除提交的 Git 标签发生了什么

What happen to Git tags pointing to a removed commit

假设我执行以下操作:

  1. 创建分支X
  2. 创建标记 t(到分支 X
  3. 推送
  4. 删除分支X

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

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

参考

来自Git Basics - Tagging

Git uses two main types of tags: lightweight and annotated. A lightweight tag is very much like a branch that doesn’t change – it’s just a pointer to a specific commit.

如果删除从中创建标签的分支,则不会对标签产生任何影响。标签不包含其创建位置的引用。

如果您想了解更多关于标签与分支的信息,我建议您查看这个问题:How is a tag different from a branch? Which should I use, here?

What happen to tag 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)

is it considered as garbage?

否,因为提交仍由标记 t.

引用

What if the commit is removed?

您没有删除提交。您删除指向提交的指针,如果不再引用提交 git 某天将对它们进行垃圾回收(取决于您的配置)。

git gc

即使您删除了所有普通引用,如分支和标签,提交仍将在引用日志中引用一段时间,您可以访问它们,例如重新创建一个分支,标记它们或 cherry-pick 等等。

您可以使用 git reflog 查看 reflog。另请查看 gc.reflogExpireUnreachablegc.reflogExpire


编辑

如果不知何故git 的对象数据库已损坏。来自 .git/objects 文件已被删除 (例如,您使用文件资源管理器或命令行命令不小心将其删除)或 ref 指向非-existent git object(如提交、树或 blob 对象),如果 git 尝试访问这些对象,您将收到错误。

以下是当 git 尝试访问不存在的对象或引用不存在的对象时可能发生的错误列表。

  • 提交

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

    示例:

    fatal: Could not parse object 'master'.
    
  • fatal: unable to read tree <tree-sha1>
    

    示例:

    fatal: unable to read tree 13a3e0908e4f6fc7526056377673a5987e753fc8
    
  • blob

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

    示例:

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

查看 Git Internals 以获得更深入的了解。

我不是在解决 OP 问题中的特定场景,而是在标题中的问题:指向已删除提交的 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

所以问题 "What happens to a git tag that references a removed commit?" 的答案是……没什么。它将保留在那里,指向无效的引用,直到您使用 git tag -d <tag>.

将其删除