我不确定,但是:
- 预告片键不能有空格(因此
Reviewed By -> Reviewed-By,和Differential Revision -> Differential-Revision);
- 预告片不应以新行分隔,而应与提交提交消息分开(因此您的问题中的
Reviewed By 不被视为预告片)。
我也不推荐使用 CSV,而是使用 TSV:git 输出不知道 CSV 语法(分号和逗号转义),因此输出文档可能无法解析。
如果您的提交消息看起来像这样(- 而不是空格,没有换行符):
commit 7c87963cc
Author: XYZ <xyz@abc.com>
Date: Tue Dec 8 17:40:13 2020 +0000
[TTI] Add support for target hook in compiler.
This adds some code in the TabeleGen ...
This is my body of commit.
Reviewed-By: Sushant
Differential-Revision: https://codereviews.com/DD8822
那么下面的命令会为你工作:
git log --pretty=format:'%h%x09%an%x09%ae%x09%aD%x09%s%x09%(trailers:key=Reviewed-By,separator=%x20,valueonly)%x09%(trailers:key=Differential-Revision,separator=%x20,valueonly)'
为您的制表符分隔值输出生成简短的提交 ID、作者姓名、作者电子邮件、日期、提交消息、预告片 Reviewed-By 和预告片 Differential-Revision。
如果您不能更改旧的提交消息,因为您的历史记录不安全(它已发布,由同行拉取,您的工具绑定到已发布的提交哈希),那么您必须处理 git log 输出使用sed、awk、perl 或任何其他文本转换工具来生成您的报告。比如说,处理git log --pretty=format:'%x02%h%x1F%an%x1F%ae%x1F%aD%x1F%s%x1F%n%B' 之类的东西,其中应该以某种方式分析^B (STX) 和 EOF 之间的行(过滤您感兴趣的预告片),然后加入以^B 开头的组行,然后替换字符分别用\t 和无字符替换字段和条目分隔符。
但同样,如果您可以通过修复提交消息预告片来编辑历史记录(不确定它可能会影响多少),我建议您这样做,然后拒绝额外脚本处理 @ 无法识别的预告片的想法987654342@ 并简单地修复提交消息。
编辑 1(文本工具)
如果重写历史不是一个选项,那么实现一些脚本可能会对您有所帮助。我在编写强大的sed/awk/perl 脚本方面相当薄弱,但让我试试吧。
git log --pretty=format:'%x02%h%x1F%an%x1F%ae%x1F%aD%x1F%s%x1F%n%B' \
| gawk -f trailers.awk \
| sed '$!N;s/\n/\x1F/' \
| sed 's/[\x02\x1E]//g' \
| sed 's/\x1F/\x09/g'
它是如何工作的:
-
git 生成一个由标准 C0 C1 codes 分隔的数据组成的日志,假设您的提交消息(STX、RS 和 US)没有这样的字符——我真的不知道这是否是一个像这样使用它们的好地方,如果我在语义上正确应用它们);
-
gawk 过滤日志输出,试图解析 STX 开始的组并提取预告片,生成“两行”输出(每个奇数行用于常规数据,每个偶数行用于逗号连接的预告片值,即使对于丢失的预告片);
-
sed 成对加入奇偶行(致谢Karoly Horvath);
-
sed 移除 STX 和 RS;
-
sed 将 US 替换为 TAB。
这里是trailers.awk(同样,我不是awk 的人,不知道下面的脚本有多惯用,但它似乎可以工作):
#!/usr/bin/awk -f
BEGIN {
FIRST = 1
delete TRAILERS
}
function print_joined_array(array) {
if ( !length(array) ) {
return
}
for ( i in array ) {
if ( i > 0 ) {
printf(",")
}
printf("%s", array[i])
}
printf("\x1F")
}
function print_trailers() {
if ( FIRST ) {
FIRST = 0
return
}
print_joined_array(TRAILERS["Reviewed By"])
print_joined_array(TRAILERS["Differential Revision"])
print ""
}
/^\x02/ {
print_trailers()
print $0
delete TRAILERS
}
match($0, /^([-_ A-Za-z0-9]+):\s+(.*)\s*/, M) {
TRAILERS[M[1]][length(TRAILERS[M[1]])] = M[2]
}
END {
print_trailers()
}
简单说一下awk 脚本的工作原理:
- 假定不需要处理的记录以 STX 开头;
- 它尝试
grep 每个非“STX”行以获取Key Name: Value 模式并将找到的结果保存到临时数组TRAILERS(实际上用作多映射,如Java 中的Map<String, List<String>>)每条记录;
- 每条记录都按原样写入,但预告片会在检测到新记录之前或在 EOF 处写入。
编辑2(更好awk)
好吧,我在awk 方面真的很弱,所以一旦我阅读了更多关于awk 内部变量的信息,我发现awk 脚本可以完全重新实现,并产生一个准备好使用的类似TSV 的输出本身无需使用sed 或perl 进行任何后期处理。所以脚本的更短和改进的版本是:
#!/bin/bash
git log --pretty=format:'%x1E%h%x1F%an%x1F%ae%x1F%aD%x1F%s%x1F%B%x1E' \
| gawk -f trailers.awk
#!/usr/bin/awk -f
BEGIN {
RS = "\x1E"
FS = "\x1F"
OFS = "\x09"
}
function extract(array, trailer_key, __buffer) {
for ( i in array ) {
if ( index(array[i], trailer_key) > 0 ) {
if ( length(__buffer) > 0 ) {
__buffer = __buffer ","
}
__buffer = __buffer substr(array[i], length(trailer_key))
}
}
return __buffer
}
NF > 1 {
split($6, array, "\n")
print $1, $2, $3, $4, $5, extract(array, "Reviewed By: "), extract(array, "Differential Revision: ")
}
更简洁,更易于阅读、理解和维护。