试试这个命令:git describe --contains <commit 2> | cut -d'~' -f1
。这将以提交次数的方式将其与标签关联,仅取~
之前的部分作为标签名称(假设您的标签名称不包含~
)。
git describe --contains <commit 2> | rev | cut -d'~' -f2- | rev
,你甚至可以在标签名称中包含波浪符。但是,对于我来说,git 不允许在标签名称中使用波浪符。 - Vampiregit describe
仅使用带注释的标签。我并不完全同意 git tag
文档中的理由,但它说(引用):“带注释的标签适用于发布,而轻量级标签适用于私有或临时对象标签。因此,一些命名对象的 gitt 命令(如 git describe)默认情况下将忽略轻量级标签。” - torekgit describe
,但没有提到要使用--tags
选项运行它。所以至少值得注意一下。 - torek提交记录的箭头指向相反的方向。提交1不指向提交2,相反,提交2指向提交1。这很重要,因为...
在您绘制的图中,您只绘制了四个提交记录,没有分支或合并。也就是说,您绘制了以下内容:
A <- B <- C <- D <-- branch-tip
(我已经从数字转换为字母,因为有26个字母和只有十个一位数字,而且我根本没有使用所有的十个一位数字....) 如果你在提交 B
,那么回到提交 A
就非常容易:箭头指向那个方向。相反地,要往另一个方向走是很难的——事实上,没有辅助就不可能。
我们需要的关键帮助是一个稍后提交的标识或定位器。例如,使用名称branch-tip
,我们可以找到提交D
。从 D
开始,我们可以返回 C
,然后返回 B
,现在我们已经追踪到了一个可用的路径。
但这个图太简单了。让我们画一个带有分支的图。由于我们知道 Git 的箭头都是向后的,所以不必画内部箭头,只需使用连接线即可,当我们水平绘制时,只能向左移动。还有,让我们加入您的标签,再加上一些其他的:
tag:past
|
| tag:future
| | tag:distantfuture
v v v
A--B--C---D <-- branch1
\
E--F <-- branch2
^ ^
| |
| tag:future3
|
tag:future2
B
找到哪个未来标签,是future
还是future2
? 我们知道你既不想要future3
也不想要,但是future2
和future
都只有一步之遥离B
。branch1
的尖端或朝branch2
的尖端。您可能希望选择一个方向,您可以通过选择一个标识符来帮助Git在第一次找到提交D
或F
时找到最终返回B
的提交。git rev-list --ancestry-path
查找作为B
的后代但是给定分支尖端的祖先(不包括B
本身并包括分支尖端)的提交。git rev-list
输出中的提交的标签。 C--D
/ \
A--B G--H <-- branch-tip
\ /
E--F
D
和F
的标签,则两者与B
等距离,但两者也在祖先路径上,导致从B
到H
。B
,使用--contains
将列表限制为最终会返回到B
的标签。然后,rev-list --count
方法找到它们的“距离”。但是,如果图形中存在合并,则此计数可能有些错误。例如,在这个最后的图形中,有一圈提交,“距离”从H
到B
实际上是四个;但是从H
返回到B
的路径中有六个提交。只是其中两个——C-D
和E-F
——可以同时遍历。--ancestry-path
将测试限制为指向某个特定图形路径内的提交的标签,则git rev-list --count
度量中的轻微缺陷不会有影响,因为相同的计数缺陷将适用于所有模糊性。只有在您没有使用--ancestry-path
的情况下才会出现问题:在这种情况下,包含合并提交的标签可能产生比不包含合并提交的标签更高的计数,但实际上更接近提交B
。)git tag --contains <commit 2> | xargs -I {} sh -c 'echo "$(git rev-list --count <commit 2>..{}) {}"' | sort -n | head -n 1 | cut -d ' ' -f 2-
xargs
命令都有 -i
:你可能想要 POSIX-y 的 -I
、-J
和 -R
,并添加 -n 1
使其每行运行一次。或者只需将其管道传输到 while read ...
循环中。 :-) - torek-J
和-R
分别指什么?我在POSIX xargs
man页中没有找到它们,即使是在我的xargs
man页中也没有。那为什么我要加上-n 1
呢?在POSIX版本中,-I
已经默认做了这个操作。 - Vampire-I
显然只进行了五次替换,所以 -R
设置了数量。 -I
还设置了 -x
,这也很恼人,所以BSD的 -J
就像 -I
但不会出现恼人的情况。 :-) BSD man页面声称 -J
也不意味着 -n 1
,虽然我不确定这是如何工作的。...啊,例子说明得很清楚,是的,-J
不意味着 -n 1
。无论如何,5已经足够了,所以唯一的烦恼就是暗示的 -x
。 - torek查找最近的已注释标签:
#!/usr/bin/env python3
import fileinput
import subprocess
import sys
# Usage: script-name <commit sha1>
tag = sys.argv[1]
lightweight = True
while lightweight:
describe = subprocess.check_output(["git", "describe", "--exclude", tag, "--contains", tag])
tag = describe.partition(b"~")[0]
lightweight = subprocess.check_output(["git", "cat-file", "-t", tag]) == b"commit\n"
print(tag.decode())