Git 给定范围内的单独标签日志
Git log of tags solely, in a given range
我想做 git log --no-walk --tags --decorate=short
做的事情,但我也想检查给定范围内的标签(提交范围),而不仅仅是所有标签。
编辑:因为,git rev-list
(因此git log
)有--simplify-by-decoration
,discards 没有(分支或)标记名称指向它们的提交:
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 log
和 git rev-list
都是从一个源文件构建的。)
你在这里遇到的主要问题是,虽然 git log
/ git rev-list
很容易让你限制选择哪些提交,但 Y ^X
或 X..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 \
)
但事实并非如此,因此需要小脚本。
我想做 git log --no-walk --tags --decorate=short
做的事情,但我也想检查给定范围内的标签(提交范围),而不仅仅是所有标签。
编辑:因为git rev-list
(因此git log
)有--simplify-by-decoration
,discards 没有(分支或)标记名称指向它们的提交:
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 log
和git rev-list
都是从一个源文件构建的。)
你在这里遇到的主要问题是,虽然 git log
/ git rev-list
很容易让你限制选择哪些提交,但 Y ^X
或 X..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
:
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 \
)
但事实并非如此,因此需要小脚本。