如何列出特定git分支中的所有标签

10

我在Git仓库中有几个分支,想知道是否有一个命令列出特定分支中的所有标签,而不是整个仓库中的所有标签。

我尝试使用 git tag --contains 命令,但它的结果与预期不符。

图片1展示了所有标签及其哈希值的列表(两个标记具有相同的哈希值/提交)。 enter image description here 图片2说明我正在名为“b”的分支上。 enter image description here 图片3,我查询了哪个分支包含这两个标签的哈希值(两个标记具有相同的哈希值),它说它们在“b”分支上(我当前所在的分支)。 enter image description here

图片4描述了分支标签,它只给了我一个标签。 enter image description here

图片5也描述了指向标记的哈希值,它只显示了一个标记,而这个标记应该指向被这两个标签标记的提交。 enter image description here


2
这不是和 https://dev59.com/3HE95IYBdhLWcg3wRLwt 或 https://dev59.com/c2PVa4cB1Zd3GeqP9t2H#10603278 一样吗? - VonC
我想要的是一个简单的命令来列出分支内的所有标签,而不是一系列的命令组合。也许 Git 不会按分支索引标签。我不确定,所以才问的 :D。 - mkmostafa
1
标签(Tags)指向提交(commits),相同的提交可以存在于多个分支中。因此,它不能直接告诉您当前分支中的标签,因为它需要将所有标签与当前分支中的所有提交进行比较,并查看哪些标签指向包含在其中的提交。 - CodeManX
1
所以,如果我为特定提交创建一个标签,哈希将是相同的。就像你说的那样,它们没有列出来,只返回一个。然而,这对我很有效:git for-each-ref refs/tags | grep HASH - CodeManX
1
我很想回答你的问题,但是它已经关闭了 :( 你需要开一个新的问题,这样我才能发布我的答案。如果你这样做了,请将此问题回滚到最初的问题。顺便说一句:我给git邮件列表发了一封邮件询问 git tag --list --branch ...for-each-ref 结合使用加上 grep 似乎是检索所有标签名称的唯一方法。 - CodeManX
显示剩余10条评论
2个回答

17
使用 git tag --sort='creatordate' --merged 命令列出所有可从 HEAD 访问/到达的标签,并按时间顺序排序。
如果您不想使用 HEAD,可以指定 ref,例如:git tag --sort='creatordate' --merged mybranch

请问如何传递refname参数? - Ramkumar D
@RamkumarD 你可以将它放在末尾,例如 git tag --sort='creatordate' --merged mybranch。引用可以是标签、分支、提交哈希等。 - qwertzguy
请参考类似/重复问题的答案 https://dev59.com/3HE95IYBdhLWcg3wRLwt#39084124 - Franklin Piat

10

要打印指向特定提交的所有标签,可以这样做:

git for-each-ref refs/tags | grep HASH

或者如果您使用的是Windows,而且没有使用Cygwin或类似工具:

git for-each-ref refs/tags | find "HASH"

如果你只想要标签名称,那么你不能使用 Git 的 --format,因为我们需要它来进行 grep 操作。因此,在最后一步中(Linux/Cygwin),我们需要去掉我们不感兴趣的内容:

git for-each-ref refs/tags | grep HASH | sed -r "s/.*refs\/tags\/(.*)/\1/"

关于最初的问题:

这个代码会遍历所有分支上的所有标签,询问git哪些分支包含每个标签,并根据提供的分支名称进行筛选 - 但是要注意,它非常慢:

git for-each-ref refs/tags --format "%(refname)" | while read x
do
    if git branch --contains $x | grep -q "^[ *] master$"
        then echo $x
    fi
done

下面的引用自另一个答案速度更快:

git log --simplify-by-decoration --decorate --pretty=oneline "master" | fgrep 'tag: '

...但是如果多个标签指向相同的提交,它将会产生:

 (HEAD, tag: Test-Tag1, tag: Test-Tag2, Test-Tag3, fork/devel, devel)
 (tag: Another-Tag)
 (tag: And-Another)

(三个标签 Test-Tag* 指向同一个提交)

我编写了一个 Python 脚本,仅输出每行一个的标签名称(仅在 Windows 平台测试通过):

import os
from subprocess import call

print("-" * 80)

dirpath = r"D:\Projekte\arangodb" # << Put your repo root path here!

tagdir = os.path.join(dirpath, ".git", "refs", "tags")
commitspath = os.path.join(dirpath, "_commit_list.tmp")

# could probably read from stdin directly somewhow instead of writing to file...
# write commits in local master branch to file
os.chdir(dirpath)
os.system("git rev-list refs/heads/master > " + commitspath)

tags = {}
for tagfile in os.listdir(tagdir):
    with open(os.path.join(tagdir, tagfile), "r") as file:
        tags[file.read().strip()] = tagfile

tags_set = set(tags)

commits = {}
with open(commitspath, "r") as file:
    for line in file:
        commits[line.strip()] = 1
os.remove(commitspath)

commits_set = set(commits)

for commit in sorted(commits_set.intersection(tags_set), key=lambda x: tags[x]):
    print(tags[commit])

结果:

Test-Tag1
Test-Tag2
Test-Tag3
Another-Tag
And-Another

最后一行可以修改为print(commit, tags[commit]),这样就可以选择性地打印每个标签的提交哈希。顺便说一下,这个脚本似乎表现得非常好!

理想情况下,Git应该支持以下命令,以避免所有这些解决方法:

git tag --list --branch master

3
我正在处理“git tag --merged”,这将是最简单的方法 :) - Karthik Nayak
1
@KarthikNayak:听起来很不错!我希望它能返回某个分支的标签,即使这些标签指向的提交实际上并没有合并(即在同一分支中创建的标签,指向提交到该分支的提交)。你有什么想法何时可以期待这个功能? - CodeManX
2
这是 https://github.com/KarthikNayak/git/commits/exp,建议你跳过前面几个提交。我同意Jeff所说的,名称来自branch.c中的选项,而且尽管您的限制是针对分支,但我们希望检查标签,该选项可以扩展到任何引用,这样合并也有意义。 - Karthik Nayak
1
@IanKemp 这个已经在9月份合并到上游了:https://github.com/git/git/commit/5242860f548d1869ac2779726ad496f0ae8ab5ca。 我相信这是git v2.7.0。 - Karthik Nayak
1
@IanKemp 很高兴能帮忙 :D - Karthik Nayak
显示剩余7条评论

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