仅在给定范围内对标签进行Git记录

时间:2016-07-20 21:00:38

标签: git git-log git-tag

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

1 个答案:

答案 0 :(得分:2)

修改:作为jthill noted in a commentgit rev-list(因此git log)有--simplify-by-decoration,其中放弃提交没有(分支或)标记名称指向它们:

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

可能会做你想要的。不幸的是,测试显示它还保留了具有指向它们的分支名称的提交。 The documentation并非100%明确:

  

--simplify-by-decoration
   选择某些分支或标记引用的提交。

但稍后:

  

--simplify-by-decoration选项允许您只查看大字号    通过省略提交的历史拓扑图片    没有被标签引用。 ...

下面的原始答案(它应该有用)。

好的,听起来你想要将X..Y和&#34之类的效果结合起来;只选择有标签指向它们的提交"。

执行此类操作有两个主要的Git命令:

  • git for-each-ref,它允许您使用引用名称 - refs/名称空间内任何位置的任何名称;标签位于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语法的一个区域当然,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

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

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

请注意,这是%(object),而不是%(objectname);后者只会获得带注释的标签对象的ID。

最后,我们只想要两个临时文件中的提交ID,即我们希望comm -12除了列3(两个文件中的行)之外的所有内容都禁止{/ 1}}:

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 \
)

但它没有,因此需要小脚本。