git describe在同一个提交上使用两个标记

qgzx9mmu  于 2022-11-27  发布在  Git
关注(0)|答案(5)|浏览(155)

我们偶尔会在同一个提交中使用两个标记。当我们使用git describe提交时,git describe总是返回第一个标记。我在阅读git-describe手册页时似乎指出应该返回第二个标记(这更有意义)。

SEARCH STRATEGY
     For each committish supplied, git describe will first look for a tag which tags
     exactly that commit. Annotated tags will always be preferred over lightweight tags, 
     and tags with newer dates will always be preferred over tags with older dates. 
     If an exact match is found, its name will be output and searching will stop.

有没有办法让git describe返回第二个标记?

uujelgoq

uujelgoq1#

你有没有试过任何选项git描述?

--all
       Instead of using only the annotated tags, use any ref found in .git/refs/. This option enables
       matching any known branch, remote-tracking branch, or lightweight tag.

   --tags
       Instead of using only the annotated tags, use any tag found in .git/refs/tags. This option
       enables matching a lightweight (non-annotated) tag.
nhaq1z21

nhaq1z212#

Git在这种情况下的行为是奇怪和令人困惑的。
当我为同一个提交创建两个标记时,我注意到在.git/refs/tags中,每个标记都有自己的提交,所以理论上可以明确地 checkout 一个完全相同的标记。
实际上并非如此。
假设我有commit ABCD,我给它做了两个标签(带注解),v1.0和v2.0。
然后我有这样的东西..
master -> ABCD hotfix -> ABCD v1.0 (3423) -> ABCD v1.0 (4234) -> ABCD
当我 checkout master或hotfix这样的分支时,我注意到git只是在.git/HEAD中存储了该分支的ref,所以一切都很好,它不是二义性的,而是一个特定的分支。
当我直接 checkout 提交时,它本质上是不明确的。HEAD只包含提交的哈希值ABCD
当你 checkout 一个标签,比如v1.0或v2.0,HEAD将不包含标签ref或标签commit,而是包含commit id,就像你直接 checkout 了commit一样!
这让人困惑的地方在于,如果你 checkout 一个分支,比如master,然后 checkout 一个标签,git status和describe会显示正确的标签,也就是你 checkout 的那个标签,尽管它是模糊的!
但是,如果您随后 checkout 指向同一个标记的另一个标记,它将显示原始标记。从分支切换到标记时,会记住该标记,而从标记切换到标记时不会。
我不知道这是不是一个bug,也不知道git是怎么做到的(我猜它会重复(.git/logs/HEAD)),但考虑到这种行为似乎是任意的,我敢猜测,如果你只是想使用一个命令来获取用户从上到下选择的内容,无论是标签、分支还是提交,那么我不认为这是可靠的支持。
如果您尝试使用命令自动获取版本,那么您需要让用户手动输入标记,或者准备一些程序来消除冲突。
轻量级标签(没有注解,本身没有提交,只是一个指向提交的指针)也有同样奇怪的行为。考虑到它在一种情况下能够准确地保存用户 checkout 的位置,而在另一种情况下却失败了,我认为这是一个bug,应该报告。
这种情况的用例是用户只 checkout 一个东西,即使这个标识符可能指向有很多其他标识符的东西。为了方便起见,你想把用户输入的标识符作为构建的标识符使用。Git记住标识符的能力令人费解地不一致。
在这种情况下,你的脚本将需要尝试导出一个最佳标识符,但如果标识符不明确,它将产生一个错误。你不能依赖git status或describe,因为有时它们不会产生最后一次 checkout 的内容,当从一个标记切换到另一个标记,而不是从分支切换到另一个标记时。
这可以在.git/logs/HEAD中看到,它似乎包含分支到标记报告,但一旦你在一个标记上,就不会记录任何东西。
Describe似乎总是返回最近注解的(非轻量型)标签。如果您混用标签类型,就不应该假设行为一致。轻量型标签似乎也会使用最新的版本(可能是基于文件的时间戳而不是提交时间),但如果没有--all--tags,就不会被搜索。带注解的标签似乎优先于较新的轻量级标签。
要得到当前标签的所有标识符,唯一方便的方法就是运行git show-ref,并使用dereference和grep来获取当前提交的标识符。

pb3s4cty

pb3s4cty3#

我在同一个commit上有两个标记约定,并希望保留git describe的特性,如dirty、sha和标记后的commit计数等。因此,在git version 2.24.1中,由于我在一个标记和另一个标记中有一个唯一的区分字符串,我只使用了匹配操作符。您也可以使用exclude
git describe --tags --match '*xXx*'

vof42yt1

vof42yt14#

两种方法,视您的需要而定。

方法1

git tag -l | sort -V | tail -1

如果要检查特定格式,例如语义版本

git tag -l | grep "v[0-9]*.[0-9]*.[0-9]*$" | sort -V | tail -1

方法2

git tag --sort=committerdate | tail -1

如果要检查特定格式,例如语义版本

git tag --sort=committerdate | grep "v[0-9]*.[0-9]*.[0-9]*$" | tail -1
nwlls2ji

nwlls2ji5#

据我所知,'git describe'无法消除轻量级标记的歧义,所以打印它遇到的第一个标记。这个代码片段假设标记遵循一个可按'sort -R'排序的模式,并将在给定的SHA上返回'latest'标记:

git tag --contains SHA | sort -R | tail -1

相关问题