在我的一个项目中,我尝试在签出分支后或从origin/master
获取最新标签。如果我运行git tag -l --sort=-creatordate --merged | head -n1
或git describe
,则会得到相同的结果,但其结果来自过去的标签。如果我摆脱了--merged
,它会在项目中显示正确的最新标签。
签出一个特定的分支会给我回购代码中正确的,最后一个已知的标签,但是如果它来自origin/master
或FETCH_HEAD
,它会给我一个过去的标签。
我主要是想知道--merged
标志是如何工作的,因为手册页只说了Only list tags whose commits are reachable from the specified commit
。
答案 0 :(得分:1)
这有两部分:
git tag -l --merged
的工作原理,它使用的是概念本身。Reachability是图的属性,或者在Git的情况下,是有向图的属性。请查阅Wikipedia文章或Think Like (a) Git,以获得适当的说明。 (或者查看我的众多StackOverflow答案之一,该答案显示了如何确定哪些分支包含各种提交。)其余部分假设您已经了解了可达性。
在Git中的 tag 只是一个奇特的指针:实际上,是指向一个特定提交的箭头。但是Git中的标签还有另外一件特别的事情:它们可以指向 tag对象,而不是直接指向提交。 1 标签对象具有{{ 1}}或git tag -a
的消息。然后,标记对象将保存基础提交的原始哈希ID。
这使我们想到了文档中的措辞:
手册页上只显示[
git tag -m
]仅列出可从指定提交中提交的列表标记。
我们运行:
--merged
所以我们选择一个提交。那就是“指定的提交”。
git tag -l --merged <commit-specifier>
操作现在将遍历每个标签。标签要么直接指向提交,要么指向指向提交的带注释的标签对象。该提交存在于整个Git提交图中。 git tag -l
适用的问题是:我们可以从指定的提交中到达带标签的提交吗?
如果我们可以到达已标记的提交,则--merged
将列出标记。如果不是这样(或者我们必须跳过标记,因为它毕竟不会标记提交),则git tag -l
会忽略标记。
1 实际上允许标记名称指向树或Blob对象,以及指向提交或带注释的标记对象。在这种情况下,根本没有提交,git tag -l
只会忽略该标签。同样,带注释的标记对象实际上可以引用任何其他类型的对象,而不仅仅是提交对象。因此,解析标签名称的真正规则是:
我们现在知道标签所指向的对象。如果是提交,则是此git tag -l --merged
列表的候选对象。如果不是,则不是。