给定一个 git 标签,我该如何判断它是注释标签还是轻量级标签?

120

我输入 git tag 命令,它会列出当前的标签:

1.2.3
1.2.4

我如何确定这些中哪一个是已注释的,哪一个是轻量级的?


3
git tag -n命令对你有什么作用吗? - Oxymoron
1
一个标签注释不是提交信息。你无法在git-log(1)中看到它;你需要使用git-show(1)。 - Oxymoron
git tag -n 很有趣!但对于我的特定问题来说并不是万无一失的解决方案。 - G. Sylvie Davies
3
我喜欢使用 "git show-ref -d --tags" 命令。 - G. Sylvie Davies
5个回答

108

git for-each-ref 默认情况下会告诉你每个引用的名称,ID和类型。如果只想限制在标签上,可以使用 git for-each-ref refs/tags

输出有三个字段:对象的哈希值,对象的类型以及引用该对象的 refs/tags 中的名称。所谓的“轻量级”标签是指引用了一个 commit¹ 对象的 refs/tags 中的名称。而“注释型”标签是指引用了一个 tag 对象的 refs/tags 中的名称。

- Solomon Slow(评论中的内容)

以下是一个示例:

$ git for-each-ref refs/tags                                           
902fa933e4a9d018574cbb7b5783a130338b47b8 commit refs/tags/v1.0-light
1f486472ccac3250c19235d843d196a3a7fbd78b tag    refs/tags/v1.1-annot
fd3cf147ac6b0bb9da13ae2fb2b73122b919a036 commit refs/tags/v1.2-light

带有一些格式:

$ git for-each-ref \
  --format="%(if:equals=tag)%(objecttype)%(then)a %(else)%(if:equals=blob)%(objecttype)%(then)b %(else)  %(end)%(end)%(align:20,right)%(refname:short)%09%(objectname:short)%(end)%09%(if:equals=tag)%(objecttype)%(then)@%(object) %(contents:subject)%(else)%(end)" \
  --sort=taggerdate \
  refs/tags

    v1.2-light  fd3cf14 
b       forsam  633de05 
a   v1.1-annot  1f48647 @1e25186bcf26d260754b6ebf6b236e92eeadc69b annotation comment
    v1.0-light  902fa93

如果只针对一个引用进行操作,您可以在本地引用上使用git cat-file -t命令来执行,例如:

$ git cat-file -t v1.0-light
commit
$ git cat-file -t v1.1-annot
tag

¹ 标签可以引用 Git 中的任何对象,如果你想让你的朋友只获取一个文件而你的仓库有一个 Git 服务器,你可以使用 git tag forsam :that.file 命令,然后 Sam 就可以获取并显示它了。大多数方便的命令不知道如何处理标记的 blob 或 tree,但是像 update-index 等核心命令则可以。


10
当我尝试这个操作时,输出结果列出了每个标签是 commit 还是 tag。 我猜想这表示轻量标签和附注标签的区别? - Stevoisiak
4
@StevenVascellaro 是正确的,轻量级标签就是以"refs/tags"开头的本地引用,可以指向任何东西。对象数据库中的标签不仅仅有一个名称,而且像其他对象一样可以被传送。Git会为对象数据库中的每个标签创建本地引用,因此区分有些模糊,在项目的工作流程设置好之后一般没什么人需要关注这个。 - jthill
4
所以,“commit”是轻量级的,“tag”则是有注释的? - Pontiacks
9
@Pontiacks,输出有三个字段:对象的哈希值、对象的类型以及指向该对象的refs/tags中的名称。所谓的“轻量级”标签是指指向commit对象的refs/tags中的名称。而“附注型”标签是指指向tag对象的refs/tags中的名称。 - Solomon Slow

54

git show-ref -d --tags 命令可以实现这一点,因为轻量级标签在输出中只出现一次,而带注释的标签会出现两次。此外,只有带注释的标签在输出中包含 "^{}" 解引用运算符。

588e9261795ec6dda4bd0a881cf1a86848e3d975 refs/tags/1.2.3
7fe2caaed1b02bb6dae0305c5c0f2592e7080a7a refs/tags/1.2.4
588e9261795ec6dda4bd0a881cf1a86848e3d975 refs/tags/1.2.4^{}

然后可以使用unix的sort、sed、cut和uniq命令来处理输出,使输出更易读:

git show-ref -d --tags       | 
cut -b 42-                   | # to remove the commit-id
sort                         |
sed 's/\^{}//'               | # remove ^{} markings
uniq -c                      | # count identical lines
sed 's/2\ refs\/tags\// a /' | # 2 identicals = annotated
sed 's/1\ refs\/tags\//lw /'   

对于我的原始仓库(来自我的问题),它输出:

  lw 1.2.3
   a 1.2.4

(例如,1.2.3版本是“轻量级”的,“1.2.4”版本被注释了)。


41

获取标签名称(例如foo),然后执行git cat-file -t foo命令。如果它是一个带注释的标签,cat-file会告诉你这是一个“tag”。如果它是一个简单标签,cat-file会告诉您这是一个“commit”。

更新:正如oxymoron在他的评论中所说,git show也可以使用,但它会提供比只是标签类型更多的信息。


7
对于“给定的标签”(如问题中所述),这似乎是迄今为止最好的答案。 - phils
3
这是一个很好的回答,关键在于 "git cat-file" 命令中使用的 "-t" 选项。如 man 手册所解释的那样:"-t 不显示内容,而是显示由<object>标识的对象类型。" - G. Sylvie Davies
或者使用 git cat-file -p foo 命令查看差异和消息+元数据。 - kxr

15
请尝试使用git describe命令。
默认情况下(没有--all或--tags选项),git describe只显示带有注释的标签。
参考链接:https://git-scm.com/docs/git-describe

2
这并不显示所有已注释的标签。它只显示那些在同一分支上的标签。如果您正在遵循基于主干的开发,并在代码冻结时从主干分支出并在即将发布时对该分支进行标记,则该标记不会位于与主干相同的分支上,因此git describe将无法显示它。 - codingdave
@codingdave 这不完全正确,但只有在提供 --first-parent 时才是这样。无论如何,问题不是获取最新标签,而是特定标签是否被注释所以 @Oxymoron 的回答也不对,因为它只能在最好的情况下显示最新的注释,而不能列出所有标签是否被注释 - childno͡.de
@childno.de 哈哈,晚上好!让我们复活这个七年前的答案。首先是个人更新,我现在是一个父亲,已婚,拥有自己的房子。我和写这篇答案的那个人相比,是一个完全不同的人了。但也许我的假设是,提问者会很快发现这一点,并能够将 git describegit tag 的输出进行比较,以获取他们正在寻找的信息。我不能确定,但我感谢你指出这一点。我承认我本可以做得更好。我的答案是在问题发布后9分钟发布的,所以我可能在竞争中。 - Oxymoron

2
如果有人想要检查单个标签,只需执行git show <tag-name>即可。如果该标签是轻量级的,则输出将与常规提交完全相同。
commit <hash> (<tags>, <branches>)
Author: John Doe <john@doe.com>
Date:   Wed Apr 12 22:29:20 2023 +0200

The message of the actual commit...

但如果它被注释了,输出将会以以下方式开始,然后是提交信息。

tag <tag-name>
Tagger: John Doe <john@doe.com>
Date:   Wed Apr 12 22:29:20 2023 +0200

The message of the annotated tag...

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