如何判断给定的 git 标记是带注释的还是轻量级的?

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

1.2.3
1.2.4

如何确定哪些是带注释的,哪些是轻量级的?

21676 次浏览

Please try using git describe

https://git-scm.com/docs/git-describe

By default (without --all or --tags) git describe only shows annotated tags.

Get the tag name (say foo) and then do a git cat-file -t foo. If it's an an annotated tag, cat-file will tell you that it's a "tag". If it's a simple tag, cat-file will tell you that it's a "commit".

Update: As oxymoron said in his comment, git show works too but it gives you more information than just what kind of tag it is.

The git show-ref -d --tags command sort of does it, since lightweight tags occur once in the output, and annotated tags occur twice. Also, only annotated tags include the "^{}" dereference operator in the output.

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

And that output can than be massaged with the unix sort, sed, cut, and uniq commands to make the output more readable:

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 /'

For my original repo (from my question) it outputs this:

  lw 1.2.3
a 1.2.4

(e.g., 1.2.3 was "lightweight" and "1.2.4" was annotated).

git for-each-ref tells you what each ref is to by default, its id and its type. To restrict it to just tags, do git for-each-ref refs/tags.

[T]he output has three fields: The hash of an object, the type of the object, and the name in refs/tags that refers to the object. A so-called "lightweight" tag is a name in refs/tags that refers to a commit¹ object. An "annotated" tag is a name in refs/tags that refers to a tag object.

- Solomon Slow (in the comments)

Here is an example:

$ 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

To do this for just one ref, you can use git cat-file -t on the local ref, to continue the example:

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

¹ tags can refer to any Git object, if you want a buddy to fetch just one file and your repo's got a git server, you can git tag forsam :that.file and Sam can fetch it and show it. Most of the convenience commands don't know what to do with tagged blobs or trees, but the core commands like update-index and such do