Git - 检测提交是否已签署

7
有没有任何git命令或更简单的格式来确定提交是否已签署?
3个回答

22

使用 Git 1.7.9, Oct. 2011,你可以使用 git log --show-signature(在Kris回答中提到),但是在2.10版本(2016年第三季度)中,你可以简单地设置git config log.showSignature true,这将适用于git-loggit-showgit-whatchangedgit-reflog


为了方便筛选"Signed-off-By",现在(Git 2.12,2017年第一季度)你可以仅记录提交信息中的“尾注”部分。(尾注包括"Signed-off-By"和其他"Acknowledged By"消息)

查看提交 b1d31c8提交 d9f31fb(2016年11月19日)由Jacob Keller (jacob-keller)

(由Junio C Hamano -- gitster --合并在提交 f008159中,2016年12月19日,Git 2.12.0-rc0)

pretty: 添加%(trailers)格式以显示提交消息的附加信息

除了 %(subject)%(body) 和 "git log --pretty=format:...",还学到了一个新的占位符 %(trailers)%(contents:trailers)
你还有git interpret-trailers,它在Git 2.14.x/2.15(2017年第三季度)刚刚更新。

请查看 提交 5a0d0c0(2017年8月20日)由Martin Ågren (``)提交。
请查看提交 58311c6提交 cc1735c提交 a388b10提交 99e09da提交 0000239提交 fdbdb64提交 56c493e (2017年8月15日),以及提交 8abc898 (2017年8月10日)由Jeff King (peff)提交。
(由Junio C Hamano -- gitster --合并于提交 06cf4f2,2017年8月27日)

"git interpret-trailers" 已经学会了一些"--parse" 和其他几个选项,以便脚本更容易从提交日志消息中获取现有的 trailer 行。
git log --pretty=format:%(trailers:only:unfold)

实际上:
git log --pretty=format:%(trailers:only,unfold)
                                     ^^^^^

请参阅提交 84ff053(2017年10月1日)由Taylor Blau(ttaylorr提交。
(由Junio C Hamano -- gitster --提交 436b359中合并,2017年10月7日)

pretty.c:使用“,”分隔"%(trailers)"参数

为了准备将一致的"%(trailers)"原子选项添加到git-for-each-ref(1)的"--format"参数中,将pretty.c中的"%(trailers)"改为用","而不是":"分隔子参数。 多个子参数可以使用"%(trailers:unfold,only)"或"%(trailers:only,unfold)"给出。 此更改消除了"顶级"参数和 trailers 原子本身的参数之间的歧义。与"%(upstream)"和"%(push)"原子的行为一致。
注意:这在 Git 2.20 (2018年第4季度) 版本更加稳健,因为 "git interpret-trailers" 及其底层机制存在有缺陷的代码,试图忽略提交日志消息后的补丁文本,从而在各种代码路径中触发,始终只获取日志消息而不获取此类输入。
查看提交 66e83d9, 提交 ffce7f5, 提交 e5fba5d, 提交 1688c9a, 提交 c188668, 提交 00a21f5, 提交 a3b636e, 提交 0d2db00 (2018年8月23日) 由Jeff King (peff)提交。
(由Junio C Hamano -- gitster --合并于提交 fba9654, 2018年9月17日) sequencer:在解析预告片时忽略“---”分隔符。

When the sequencer code appends a signoff or cherry-pick origin, it uses the default trailer-parsing options, which treat "---" as the end of the commit message.
As a result, it may be fooled by a commit message that contains that string and fail to find the existing trailer block. Even more confusing, the actual append code does not know about "---", and always appends to the end of the string.
This can lead to bizarre results.

E.g., appending a signoff to a commit message like this:

 subject

 body
 ---
 these dashes confuse the parser!

 Signed-off-by: A

results in output with a final block like:

 Signed-off-by: A

 Signed-off-by: A

The parser thinks the final line of the message is "body", and ignores everything else, claiming there are no trailers.
So we output an extra newline separator (wrong) and add a duplicate signoff (also wrong).

Since we know we are feeding a pure commit message, we can simply tell the parser to ignore the "---" divider.


Git 2.22(2019年第二季度)增加了几个选项:
查看提交 0b691d8提交 fd2015b提交 d9b936d提交 250bea0提交 3e3f347(2019年1月28日),提交 4f732e0(2019年1月29日)和提交 4261775(2018年12月8日)由Anders Waldenborg(wanders
(由Junio C Hamano -- gitster --提交 42977bf中合并,2019年3月7日) 漂亮:在`%(trailers)`中添加对`separator`选项的支持。

By default trailer lines are terminated by linebreaks ('\n').
By specifying the new 'separator' option they will instead be separated by user provided string and have separator semantics rather than terminator semantics.
The separator string can contain the literal formatting codes %n and %xNN allowing it to be things that are otherwise hard to type such as %x00, or comma and end-parenthesis which would break parsing.

E.g:

$ git log --pretty='%(trailers:key=Reviewed-by,valueonly,separator=%x00)'

而且:

pretty: 在 %(trailers) 中添加对 "valueonly" 选项的支持

With the new "key=" option to %(trailers) it often makes little sense to show the key, as it by definition already is knows which trailer is printed there.
This new "valueonly" option makes it omit the key when printing trailers.

E.g.:

$ git show -s --pretty='%s%n%(trailers:key=Signed-off-by,valueonly)' aaaa881

will show:

upload-pack: fix broken if/else chain in config callback
Jeff King <peff@peff.net>
Junio C Hamano <gitster@pobox.com>

解析器对 "git for-each-ref --format=...(man)" 的解析过程中,在解析 "%(trailers...)" 这个元素时太过宽松,并忘记了 "trailers" 和 "trailers:<modifiers>" 是唯一允许的两种形式。这个问题已经在 Git 2.29 (2020年第四季度) 中得到修正。
查看提交2c22e10提交a8e0f50(2020年8月21日)由Hariom Verma (harry-hov)
(由Junio C Hamano -- gitster --提交e177238中合并,2020年8月31日)

ref-filter:如果缺少:,'contents:trailers'会显示错误” “辅导员:Christian Couder” “辅导员:Heba Waly” “帮助者:Eric Sunshine” “签署者:Hariom Verma”
“如果在'trailers'参数之前缺少冒号,则'contents'原子不会显示任何错误。” “例如:%(contents:trailersonly)能够工作,但实际上不应该。” “这绝对不是预期的行为。” “让我们修复这个错误。”
通过Git 2.31(2021年第一季度),"--format=%(trailers)"机制得到增强,使得为机器消费设计输出更加容易。
查看提交 058761f提交 9d87d5a提交 8b966a0提交 2762e17(2020 年 12 月 9 日),以及提交 7c1f79f(2020 年 12 月 6 日),作者为Ævar Arnfjörð Bjarmason (avar)
(由Junio C Hamano -- gitster --合并于提交 b62bbd3,2021 年 1 月 6 日)

漂亮的格式 %(trailers):添加一个"keyonly"

签名:Ævar Arnfjörð Bjarmason

Add support for a "keyonly". This allows for easier parsing out of the key and value. Before if you didn't want to make assumptions about how the key was formatted. You'd need to parse it out as e.g.:

--pretty=format:'%H%x00%(trailers:separator=%x00%x00)' \
                   '%x00%(trailers:separator=%x00%x00,valueonly)'

And then proceed to deduce keys by looking at those two and subtracting the value plus the hardcoded ": " separator from the non-valueonly %(trailers) line. Now it's possible to simply do:

--pretty=format:'%H%x00%(trailers:separator=%x00%x00,keyonly)' \
                '%x00%(trailers:separator=%x00%x00,valueonly)'

Which at least reduces it to a state machine where you get N keys and correlate them with N values. Even better would be to have a way to change the ": " delimiter to something easily machine-readable (a key might contain ": " too). A follow-up change will add support for that.

I don't really have a use-case for just "keyonly" myself. I suppose it would be useful in some cases as "key=*" matches case-insensitively, so a plain "keyonly" will give you the variants of the keys you matched. I'm mainly adding it to fix the inconsistency with "valueonly".

pretty-formats现在包含在其man page中:

  • 'keyonly[=<BOOL>]': 仅显示尾部的键部分。
  • 'valueonly[=<BOOL>]': 仅显示尾部的值部分。

以及:

查看提交 058761f提交 9d87d5a提交 8b966a0提交 2762e17(2020年12月9日)和提交 7c1f79f(2020年12月6日),作者为Ævar Arnfjörð Bjarmason (avar)
(由Junio C Hamano -- gitster --合并于提交 b62bbd3,2021年1月6日)

pretty format %(trailers):添加一个"key_value_separator"

签名作者:Ævar Arnfjörð Bjarmason

"%(trailers)"的漂亮格式中添加一个"key_value_separator"选项,与现有的"separator"参数一起使用。
结合这两个选项,可以轻松生成机器可读的(例如\0\0\0分隔的)格式输出。

正如之前添加了"keyonly"的提交中所详述的那样,在添加这个"key_value_separator"选项之前,从"%(trailers)"中提取结构化数据是非常繁琐的。
从这里添加的测试中可以看出,现在提取这些数据变得非常简单。

pretty-formats现在在其man page中包含以下内容:

  • 'key_value_separator=<SEP>': 指定插入在尾行之间的分隔符。如果没有提供此选项,则每个尾行键值对之间用“:”分隔。
    否则,它与上面的'separator=<SEP>'具有相同的语义。

使用 Git 2.38(2022 年第三季度),文档更新。

请参阅 提交 b46dd17(2022 年 8 月 30 日)由 Christian Couder(chriscool 提交。
(由 Junio C Hamano -- gitster -- 合并于 提交 00b0199,2022 年 9 月 9 日)

文档:澄清尾随内容的空格规则

签名:Christian Couder

在2016年11月2日,Git v2.12.0-rc0的提交e431956(“trailer:在解析分隔符时更严格”,合并列在批次#2中)限制了git interpret-trailers(man)在读取trailers时允许的空白字符数量。

此外,在2016年10月21日,Git v2.11.0-rc0的提交60ef86a(“trailer:支持折叠到多行的值”,合并列在这里中)更新了文档,但没有明确说明折叠值新行开头允许多少个空白字符。

git解释者现在在其手册页面中包含以下内容:

读取备注时,标记前面或内部不能有空格,但可以在标记和分隔符之间添加任意数量的普通空格和制表符。

值前面、内部或后面可以有空格。

该值可以跨多行拆分,每个后续行都以至少一个空格开头,就像RFC 822中的“折叠”一样。


当 "git commit --trailer=..."(man) 调用 interpret-trailers 机制时,它知道传递给 interpret-trailers 的是一个完整的日志消息而没有任何补丁,但是未能通过传递 "--no-divider" 选项来表达这一点:这个问题已经在 Git 2.42 (Q3 2023) 中得到了修正。
查看 commit be3d654(2023年6月17日)由 Jeff King (peff) 提交。
(由 Junio C Hamano -- gitster -- 合并于 commit 8d5c5a0,2023年6月26日)

commit:将--no-divider传递给interpret-trailers 报告者:eric.frederich@siemens.com 签署者:Jeff King
git-commit(man)遇到任何--trailer选项时,它会通过git-interpret-trailers对COMMIT_EDITMSG文件进行处理。
但是它在处理时没有传递--no-divider,这意味着interpret-trailers将寻找"---"分隔符来标志提交消息的结尾。

在这种情况下,这种行为毫无意义;我们知道我们有一个完整且独立的提交消息,不需要进一步解析。
结果是,如果提交消息包含一个"---"标记(否则在语法上没有意义),就会出错,新的trailers会插入到错误的位置。

我们可以通过传递--no-divider来修复这个问题。

这正是在1688c9a中添加它的确切情况(interpret-trailers: allow suppressing , 2018-08-22, Git v2.20.0-rc0 -- merge listed in batch #1)(interpret-trailers:允许禁止"---"分隔符,2018-08-22)。
正如该提交的消息中所提到的,它只是添加了机制,还需要进一步的补丁来触发各种调用者。
我们当时在几个地方做了这样的修复,比如ffce7f5sequencer: ignore , 2018-08-22, Git v2.20.0-rc0 -- merge listed in batch #1)(sequencer:解析trailers时忽略"---"分隔符,2018-08-22),但显然漏掉了这一个。


1
这是一个非常详尽的回答!我遇到的问题是,无论我做什么,预告片似乎都不起作用,它总是显示整个正文。我想我可能也对“预告片”从哪里获取有些困惑。它是源自于前面的%s值吗?比如%b%(trailers:...)会在正文上执行预告片吗? - Brain2000
@Brain2000 你使用的 Git 版本是什么?你能否发布一个完整提交消息的示例,以便从中提取 trailers? - VonC
1
这是一个非常详尽的答案。谢谢! - larsks
@larsks 谢谢。你最近的文章(https://blog.oddbit.com/post/2021-02-27-git-doc-tools/)很有趣。你在 Stack Overflow 的回答中使用了 git dot 生成的图表吗? - VonC
我还没有,但是上周我刚刚把这个工具拼凑在一起。 - larsks

3

在Git 2.4及以上版本中,您可以使用git log --invert-grep --grep="Signed-off-By"。(--invert-grep选项在2.4版中添加。)


0
git log --show-signature
git show --show-signature

--show-signature 通过将签名传递给gpg --verify并显示输出来检查已签署提交对象的有效性。

这实际上与问题的主题无关(该问题询问某些项目中添加到提交消息中的“signed-off-by”伪标题)。 - larsks

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接