如何在git中提交之前找到最近的标签

c9x0cxw0  于 2023-05-05  发布在  Git
关注(0)|答案(4)|浏览(166)

我试图在一个特定分支中找到提交之后最近的标记。
我知道git describe会返回并找到最近的带有标签的祖先,但是我该如何向相反的方向移动呢?
例如:

给定commit 2,我想返回future标签。其中git describe将返回past标签。

tktrz96b

tktrz96b1#

git describe --contains <commit 2> | cut -d'~' -f1怎么样?因为这将通过提交次数从标记中引用回<commit 2>,所以只取~之前的部分作为标记名称(假设标记名称不包含~)。

myss37ts

myss37ts2#

提交的箭头指向另一个方向。提交1不指向提交2;而是将2个点提交给提交1。这很重要因为。。
在你的图中,你只画了四个提交,既没有分支也没有合并。也就是说,您已经绘制了以下内容:

A <- B <- C <- D   <-- branch-tip

(我已经从数字切换到字母了,因为有26个字母,只有10个一位数的数字,并不是说我已经用完了所有的10个一位数的数字....)如果你正在提交B,返回提交A是非常容易的:就是箭头所指的方向很难--事实上,没有帮助是不可能的--走另一条路。
我们需要的关键帮助是一个“稍后”提交的标识或定位器。例如,使用名称branch-tip,我们可以定位commit 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

现在,您希望为提交Bfuturefuture2找到哪个未来标记?我们知道您既不想要future3也不想要distantfuture,但是future2future都与B仅一步之遥。
关键是它们是朝着某个方向迈出的一步:朝向branch1的尖端或朝向branch2的尖端。您可能希望选择一个方向,您可以使用与帮助Git首先找到提交DF相同的方法,通过选择一个标识符来定位最终返回到B的提交。
如果你确实想控制方向,你会想使用git rev-list --ancestry-path来查找那些是B的后代,但是是给定分支尖端的祖先的提交(不包括B本身,包括分支尖端)。
然后,将这个提交列表与类似Vampire's answer的内容结合起来,这样您就可以只查看指向这个祖先路径上的提交的标记。也就是说,从“tags that contain commit B”列表中抛出任何指向git rev-list输出中 not 的提交的标签。
请注意,这并不能解决在图中既有分支又有合并的情况下发生的问题:

C--D
    /    \
A--B      G--H   <-- branch-tip
    \    /
     E--F

在这里,如果有标签指向提交DF,两者都与B等距,但两者也都在从BH的祖先路径上。
请注意,Vampire's answer只是使用 all tags 来定位可能返回到B的后续提交,使用--contains将列表限制为 do 的标签,最终返回到B。然后rev-list --count方法找到它们的“距离”。但是如果图中有合并,这个计数可能有点缺陷。例如,在最后一个图中,使用提交环,从HB的“距离”实际上是 * 4 *;但是在从H返回到B的路径中有 * 六个提交 *。只是其中的两个-C-DE-F-可以并行遍历。
(Note:如果你 * 正在 * 使用--ancestry-path将测试限制在指向某个特定图路径内的提交的标记上,那么git rev-list --count度量中的轻微缺陷将不重要,因为相同的计数缺陷将适用于所有二义性。只有当你 * 不 * 使用--ancestry-path时才有问题:在这种情况下,包含合并提交标签可以产生比不包含合并提交的标签高得多的计数,但实际上“更接近”提交B。)

dkqlctbz

dkqlctbz3#

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-

最接近的是由提交量决定的。如果有多个具有相同距离的,则不能保证您会得到哪个。如果你想让所有的都有相同的最小距离,从管道中删除head调用。

**注意:**这在合并的情况下可能不是最佳的,如果你在有问题的提交之后分支和合并了这些分支,并且在合并之后有一个标签,那么两个分支的提交都会增加提交量,从而增加距离。

sh7euo9m

sh7euo9m4#

查找最近的注解标记:

#!/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())

相关问题