指向已删除提交的 Git 标签发生了什么
What happen to Git tags pointing to a removed commit
假设我执行以下操作:
- 创建分支
X
- 创建标记
t
(到分支 X
)
- 推送
- 删除分支
X
标签 t
发生了什么?它只是漂浮在那里吗?它被认为是垃圾吗?
我应该在删除分支本身之前删除所有指向分支的标签吗?
参考
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 某天将对它们进行垃圾回收(取决于您的配置)。
即使您删除了所有普通引用,如分支和标签,提交仍将在引用日志中引用一段时间,您可以访问它们,例如重新创建一个分支,标记它们或 cherry-pick 等等。
您可以使用 git reflog
查看 reflog。另请查看 gc.reflogExpireUnreachable
和 gc.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>
.
将其删除
假设我执行以下操作:
- 创建分支
X
- 创建标记
t
(到分支X
) - 推送
- 删除分支
X
标签 t
发生了什么?它只是漂浮在那里吗?它被认为是垃圾吗?
我应该在删除分支本身之前删除所有指向分支的标签吗?
参考
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 某天将对它们进行垃圾回收(取决于您的配置)。
即使您删除了所有普通引用,如分支和标签,提交仍将在引用日志中引用一段时间,您可以访问它们,例如重新创建一个分支,标记它们或 cherry-pick 等等。
您可以使用 git reflog
查看 reflog。另请查看 gc.reflogExpireUnreachable
和 gc.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>
.