Git 给定范围内的单独标签日志

Git log of tags solely, in a given range

我想做 git log --no-walk --tags --decorate=short 做的事情,但我也想检查给定范围内的标签(提交范围),而不仅仅是所有标签。

编辑:因为git rev-list(因此git log)有--simplify-by-decorationdiscards 没有(分支或)标记名称指向它们的提交:

git log --simplify-by-decoration --decorate=short X..Y

可以为所欲为。不幸的是,测试表明它还会保留具有指向它们的分支名称的提交。 The documentation 不是 100% 清楚这一点:

--simplify-by-decoration
Commits that are referred by some branch or tag are selected.

但后来:

The --simplify-by-decoration option allows you to view only the big picture of the topology of the history, by omitting commits that are not referenced by tags. ...

原始答案在行下方(应该有效)。


好的,听起来您想将 X..Y 和 "select only commits that have a tag pointing to them" 之类的效果结合起来。

有两个主要的Git命令可以进行这种操作:

  • git for-each-ref,它允许您使用引用名称——来自 refs/ 名称-space 中任意位置的任何名称;标签在 refs/tags/.

  • git rev-list,这实际上是与 git log 相同的命令,除了它默认显示哈希值而不是默认显示提交消息。 (还有其他细微差别,但它们非常相似,git loggit rev-list 都是从一个源文件构建的。)

你在这里遇到的主要问题是,虽然 git log / git rev-list 很容易让你限制选择哪些提交,但 Y ^XX..Y一个例子,或者 --no-walk --tags[=pattern] 另一个例子,他们不是很擅长集合交集操作。他们可以直接执行有限的联合风格操作,例如,git rev-list --no-walk --tags=foo\* --tags=bar\* --branches=baz\* 将打印每个标记有匹配 foo*bar* 名称或由分支名称指向的提交的 ID匹配 baz*.

rev-list 命令 可以 使用管道和 --stdin 进行完整的任意集联合操作,但不能使用交集。这是 Mercurial 的一个领域语法胜过 Git。当然,Mercurial 的优势在于可以在内部返回所有 Python。)

不过,您想要的是两组的交集:

  • 设置 1:您的范围选择,可能类似于 X..Y--since=date1 --until=date2

  • 设置 2:(部分或全部)标记指向的每个提交

计算这个集合交集需要一些代码。在类 Unix 系统上,我们拥有所需的所有工具:Git 本身和 comm,它可以进行集合交集。 comm 实用程序需要对其输入进行排序,因此我们将在此处通过 sort 对每个集合进行管道传输。所以我们只需要一个简短的(7 行)脚本。

我们从通常的临时文件样板开始,例如:

tf1=$(mktemp) || die "can't make first temp file"
trap "rm -f $tf1" 0 1 2 3 15
tf2=$(mktemp) || die "can't make second temp file"
trap "rm -f $tf1 $tf2" 0 1 2 3 15

现在我们使用 git rev-list:

得到第 1 组
git rev-list <specifiers> | sort > $tf1

然后我们得到第 2 组,使用 git for-each-ref。假设我们希望带注释的标签解析为它们的对象(通常是提交,但也可能是另一个带注释的标签,但如果它是另一个带注释的标签,我们会让 that 标签自行解析),我们获得第 2 组:

git for-each-ref --format='%(object)' refs/tags | sort > $tf2

注意这是%(object),不是%(objectname);后者只会让我们得到带注释的标签对象的 ID。

最后,我们只需要 both 临时文件中的提交 ID,即我们希望 comm -12 抑制除第 3 列以外的所有内容(两个行中的行)文件):

comm -12 $tf1 $tf2

此脚本的输出是要显示的提交集(按提交哈希排序确定的顺序,因此我们将依靠 git log 来确定排序顺序)。现在我们只使用您原来的 git log 命令,但是 运行 它在选定的提交上:

git log --no-walk --decorate=short --date-order $(script)

(当然这都是未经测试的)

如果 git rev-list 有一个 --stdin-intersect 选项,我们可以在 Git 和 shell:

中完成所有这些
git log --no-walk --decorate=short $( \
    git for-each-ref --format='%(object)' refs/tags | \
    git rev-list --stdin-intersect X..Y \
)

但事实并非如此,因此需要小脚本。