如何判断一个标签在 Git 中指向哪个提交?

Posted

技术标签:

【中文标题】如何判断一个标签在 Git 中指向哪个提交?【英文标题】:How to tell which commit a tag points to in Git? 【发布时间】:2010-12-24 03:52:45 【问题描述】:

我在存储库中有一堆未注释的标签,我想弄清楚它们指向哪个提交。是否有一个命令只列出标签及其提交 SHA?检查标签并查看 HEAD 对我来说似乎有点太费力了。

更新

在浏览完回复后,我意识到我真正想要的是简单地查看导致标签的历史记录,git log <tagname> 就足够了。

标记为答案的答案对于获取标签列表及其提交很有用,这就是我所要求的。通过一些 shell hackery,我确信可以将它们转换为 SHA+Commit 消息。

【问题讨论】:

我想指出 git show-ref 显示标签的 sha,而不是 repo 修订的 sha。 $ git show-ref test 08b9c774ab20e5bdb638339cf4ea2c124b0dae54 refs/tags/test $ git checkout test HEAD 现在在 c7f8831... $ git checkout 08b9c77 HEAD 现在在 c7f8831... 如果你的标签有注释,那么你需要--dereference 【参考方案1】:

一种方法是使用git rev-list。下面会输出一个标签指向的提交:

$ git rev-list -n 1 $TAG

注意这适用于带注释和未注释的标签

如果你经常使用它,你可以将它作为别名添加到~/.gitconfig

[alias]
  tagcommit = rev-list -n 1

然后调用它:

$ git tagcommit $TAG

可能的陷阱:如果您有本地结帐或具有相同标签名称的分支,此解决方案可能会得到“警告:refname 'myTag' is ambiguous”。在这种情况下,请尝试增加特异性,例如:

$ git rev-list -n 1 tags/$TAG

【讨论】:

为什么不使用git rev-parse <tag>?还是git rev-list -1 <tag> @Jakub:git rev-parse $TAG 返回标签对象的 SHA1,而不是它指向的提交。不过git rev-list -1 有效。 @mipadi:对于 un-annotated 标签,这并不重要;对于带注释的标签,您可以使用 git rev-parse $TAG^commitgit rev-parse $TAG^ 取消引用带注释/签名的标签 您可以使用:git rev-list $TAG --max-count=1 @RobinHsu:如果你有 annotated 标签,它是用git tag -agit tag -s 创建的,那么git rev-parse <tag> 会给你tag object 本身的 SHA-1,而 git rev-list -1 <tag> 将提供它所指向的 commit(修订版)的 SHA-1,与 git rev-parse <tag>^commit 相同。 HTH。【参考方案2】:

警告这仅适用于未注释的标签因此使用在一般情况下有效的公认答案更安全https://***.com/a/1862542/1586965

git show-ref --tags

例如,git show-ref --abbrev=7 --tags 会显示如下内容:

f727215 refs/tags/v2.16.0
56072ac refs/tags/v2.17.0
b670805 refs/tags/v2.17.1
250ed01 refs/tags/v2.17.2

【讨论】:

谢谢,这实际上隐藏了查看.git/packed-refs.git/refs/tags/* 的语义 嗯。它在我的存储库中有奇怪的行为: git tag -a v0.1.1-alpha a9dcc1f24cacde535523bddc22f4c69467428550; git show-ref --tags ->b784145a9a71478337f5ceae30aaac4e1b955ee5 refs/tags/v0.1.1-alpha ;见 Jakub Narebski 的回答 这行得通,虽然我想知道让git tag --verbose 也显示它们是否有意义? 这将显示标签本身的引用,而不是标签指向的提交。您需要添加 -d 标志以获取引用的提交(在第二行)。 @CharlesBailey,很公平,但问题和答案已经演变为包含带注释的标签,而git show-ref 在两种不同类型的标签上的行为不同这一事实并不明显或众所周知。跨度> 【参考方案3】:

只需使用git show <tag>

但是,它也会转储提交差异。要省略这些差异,请使用git log -1 <tag>。 (感谢@DolphinDream 和@demisx!)

【讨论】:

这样,当一个问题有许多不同的可能答案时,首先发布的答案会首先获得投票 - 将它们放在列表的顶部,从而在以后获得更多的投票。这是一个基于响应速度而不是响应质量的偏置反馈回路。只要有足够的想象力,这个问题是可以解决的。 “最佳解决方案”有什么用?如果感兴趣的是找出提交的 SHA,则标记指向“git show ”不是最佳解决方案。此命令将显示提交引入的整个差异。对于仅列出提交的 SHA,标记指向“git rev-list -n 1”是正确的解决方案。 这不是 OP 问题的答案。 git show <tag> 显示差异,而不是标签指向的提交。 @demisx 你在说什么??它肯定会显示提交哈希,以及标记、日期和其他信息。试试看。 @Hlung 就像@DolphinDream 指出的那样,git show 在屏幕上转储了更多不需要的内容。它掩盖了人们正在寻找的实际提交哈希。如果你想要 oneliner,更好的命令是 git log -1 [tag-name]git log -1 --pretty=oneline [tag-name]【参考方案4】:

来自Igor Zevaka:

总结

由于大约有 4 种几乎同样可以接受但不同的答案,我将总结所有不同的给标签换肤的方法。

    git rev-list -1 $TAG (answer)。 git rev-list 输出导致$TAG 的提交,类似于git log,但仅显示提交的SHA1。 -1 将输出限制为它指向的提交。

    git show-ref --tags (answer) 将显示所有标签(本地标签和从远程获取的标签)及其 SHA1。

    git show-ref $TAG (answer) 将显示标签及其路径以及 SHA1。

    git rev-parse $TAG (answer) 将显示未注释标签的 SHA1。

    git rev-parse --verify $TAG^commit (answer) 将显示带注释和未注释标签的 SHA1。在 Windows 上使用 git rev-parse --verify %TAG%^^^^commit(四顶帽子)。

    cat .git/refs/tags/*cat .git/packed-refs (answer) 取决于标签是本地的还是从远程获取的。

【讨论】:

【参考方案5】:

对于带注释的标签,git show-ref TAG 显示标签的哈希值,而不是它指向的提交的哈希值。

git show-ref --dereference TAG 还显示了指向的提交,并添加了^

【讨论】:

【参考方案6】:

使用

git rev-parse --verify <tag>^commit

(即使对于带注释的标签也会返回提交的 SHA-1)。


如果&lt;tag&gt; 没有注释,git show-ref &lt;tag&gt; 也可以工作。并且总是有git for-each-ref(详见文档)。

【讨论】:

我更喜欢git rev-parse &lt;tag&gt;~0,它似乎也可以工作,并且不需要在 Windows 上进行特殊转义(在 Windows 上需要四个帽子 (^) 而不是一个)。后缀 ~&lt;number&gt; 给出第 个父提交,因此 ~0 产生提交本身。顺便说一句,^0 也是 ^commit 修订后缀的有效简写。【参考方案7】:

这个怎么样:

git log -1 $TAGNAME

git log -1 origin/$TAGNAME

【讨论】:

【参考方案8】:

为了得到一个标签所引用的提交的sha/hash(不是标签的sha):

git rev-list -1 &lt;tag&gt;

【讨论】:

【参考方案9】:

我也想知道“正确”的方式,但与此同时,你可以这样做:

git show mytag | head -1    

【讨论】:

带有提交标题git show --oneline mytag | head -1【参考方案10】:

Git-2 后的简短回答

我知道这个问题已经存在很长时间了。 CB Bailey 的回答是 100% 正确的:git show-ref --tags --abbrev

我更喜欢这个,因为它使用了git tag

git tag --list --format '%(refname:short) %(objectname:short)'

简单。短。

使用此命令将其别名为git taglist

git config --global alias.taglist "tag --list --format '%(refname:short) %(objectname:short)'"

【讨论】:

对于带注释的标签,这会给出标签哈希而不是提交哈希。【参考方案11】:

尽管这已经很老了,但我想我会指出我刚刚发现的一个很酷的功能,用于列出带有提交的标签:

git log --decorate=full

它将显示在提交时结束/开始的分支,以及提交的标签。

【讨论】:

【参考方案12】:

您也可以更容易理解标签指向的位置

git log --graph |git name-rev --stdin --tags |less

然后通过/滚动到您要查找的标签。

更紧凑的视图 (--pretty=oneline) 加上所有头像 (-a) 也会有所帮助:

git log -a --pretty=oneline --graph |git name-rev --stdin --tags |less

看起来有点吓人,但如果需要,也可以在~/.gitconfig 中添加别名。

~/.gitconfig

[alias]
ls-tags = !git log -a --pretty=oneline --graph |git name-rev --stdin --tags |less

【讨论】:

【参考方案13】:

这不会显示文件名,但至少您可以了解一下存储库。

cat .git/refs/tags/*

该目录中的每个文件都包含一个指向提交的提交 SHA。

【讨论】:

这不起作用,我想,我从远程拉出标签。 .git/packed-refs 确实有效。【参考方案14】:

来自git mailing list,这是获取带有注释标签自动取消引用的标签的提交哈希列表的方法:

git for-each-ref --format='%(if)%(*objectname)%(then)%(*objectname)%(else)%(objectname)%(end) %(refname)' refs/tags

【讨论】:

【参考方案15】:

我也想知道正确的方法,但您可以随时查看:

$ cat .git/packed-refs 

或:

$ cat .git/refs/tags/*

【讨论】:

对,所以 packed-refs 和 refs/tags 的行为有些不同,packed-refs 是一个包含标签和 SHA 的文本文件,而 refs/tags/ 是一个包含以 a 命名的文本文件的目录包含 SHA 的标签。我实际上认为这样做的正确方法是使用git rev-list【参考方案16】:

这将为您提供当前的 SHA1 哈希

缩写提交哈希

git show <tag> --format="%h" --> 42e646e

提交哈希

git show <tag> --format="%H" --> 42e646ea3483e156c58cf68925545fffaf4fb280

【讨论】:

在我拥有的版本中似乎不起作用,但 git log &lt;tag&gt; -n 1 --pretty=%H 可以【参考方案17】:

如果您想查看标记 SOMETAG 的详细信息(标记器、日期等)、它指向的提交的哈希值以及有关提交但没有完整差异的一些信息,请尝试

git show --name-status SOMETAG

示例输出:

tag SOMETAG
Tagger: ....
Date:   Thu Jan 26 17:40:53 2017 +0100

 .... tag message .......

commit 9f00ce27c924c7e972e96be7392918b826a3fad9
Author: .............
Date:   Thu Jan 26 17:38:35 2017 +0100

 .... commit message .......

..... list of changed files with their change-status (like git log --name-status) .....

【讨论】:

【参考方案18】:

--format 选项可用于显示标签哈希和提交哈希,以及区分轻量级和带注释的标签。

git tag --format="%(color:bold cyan)== %(refname:short) ==%(if)%(object)%(then)%0aTag Hash: %(objectname)%0aTag Date: %(taggerdate:iso-local)%0a  Commit: %(object) %0a%0a%(contents)%(else)%0a(lightweight tag)%0a  Commit: %(objectname)%(end)%0a"

输出类似于:

== b2lightweight ==
(lightweight tag)
  Commit: 0450fae4352dbbbf088419757eda32711316a02e

== c3_annotated ==
Tag Hash: 19961d8678a09a319a9d6c398c79f27cc23d610c
Tag Date: 2021-08-06 15:18:48 -0600
  Commit: 85be6e80c109ce44d78f0ca0da8e1ec53817b24c

This is my tag message.

It has multiple lines.

Another line.

要定义为 git 别名,您可以使用 git config --global -e 编辑全局 git 配置并添加以下内容:

[alias]
    tag-verbose = tag --format='%(color:bold cyan)== %(refname:short) ==%(if)%(object)%(then)%0aTag Hash: %(objectname)%0aTag Date: %(taggerdate:iso-local)%0a  Commit: %(object) %0a%0a%(contents)%(else)%0a(lightweight tag)%0a  Commit: %(objectname)%(end)%0a'

别名仍然允许过滤,例如

C:\playground>git tag-verbose -l *b2*
== b2lightweight ==
(lightweight tag)
  Commit: 0450fae4352dbbbf088419757eda32711316a02e

有关--format 选项的更多信息,请参阅git help for-each-ref 下的“字段名称”部分。 (git help tag 声明“格式与 git-for-each-ref 相同”)

【讨论】:

【参考方案19】:

所以我有很多发布文件夹,这些文件夹可能是从几个不同的存储库之一签出的,可能是 dev、qa 或 master 分支,也可能是生产版本,从标签签出,以及标签可能被注释或不被注释。我有一个脚本,它将查看目标文件夹并以 - 形式返回答案。问题是不同版本的 git 为标签结账返回不同的状态。

所以我发现git show-ref --tags 最初工作,除了带注释的标签。但是,添加 -d 会在标签列表中添加一个单独的条目,一个用于标签,另一个用于注释(注释提交被标识为 ^,我用 sed 删除了它)。

所以这是我脚本的核心,任何人都需要它:-

REPO=`git --git-dir=$TARGET remote show origin -n | \
         grep "Fetch URL:" | \
         sed -E "s/^.*\/(.*)$/\1/" | \
         sed "s/.git$//"`

TAG=`git --git-dir=$TARGET show-ref -d --tags | \
         grep \`git --git-dir=$TARGET show --quiet --format=format:%H HEAD\` | \
         cut -d\  -f2 | \
         cut -d/ -f3 | \
         sed "s/\^$//"`

if [ "$TAG" == "" ] ; then 
  BRANCH=`git --git-dir=$TARGET show-ref --heads | \
         grep \`git --git-dir=$TARGET show --quiet --format=format:%H HEAD\` | \
         cut -d\  -f2 | \
         cut -d/ -f3`
  TAG=$BRANCH
fi

【讨论】:

【参考方案20】:

可以在下面使用,它会给出提交哈希git show -s --format=%H &lt;tag&gt;^commit

如果需要缩写的提交哈希,git show -s --format=%h &lt;tag&gt;^commit

【讨论】:

【参考方案21】:

黑客解决方案

解析.git/packed-refs并将其格式化为tag\tsha

sed -n '/ refs\/tags/  s@\([^ ]*\) refs/tags/\(.*\)@\2\t\1@; p' .git/packed-refs

【讨论】:

以上是关于如何判断一个标签在 Git 中指向哪个提交?的主要内容,如果未能解决你的问题,请参考以下文章

指向已删除提交的 Git 标记会发生啥情况

Git:如何找出标签在哪个分支上?

git:使用标签

使用竹子时重新标记后,Git 标签链接到旧提交

git 打标签

git标签管理