git - git log grep里面的内容变化
问题描述
我有一个包含 100K+ 提交的仓库。很少有提交(≈500)可能在提交消息中有一个单词 PROJECT_BOAT_COMMIT 文本。
git commit -m "PROJECT_BOAT_COMMIT: This is project boat's first commit";
每个提交都针对多个文件(添加的行、删除的行、删除的文件、添加的文件等)。
作为任何提交的一部分(不特定于 PROJECT_BOAT_COMMIT),可能已经从任何文件中添加/删除了一个特定的关键字(比如 BOAT_TODO)。
git diff ./file1
+BOAT_TODO
git diff ./file2
-BOAT_TODO
我想要做
- 过滤消息中包含 PROJECT_BOAT_COMMIT 的提交
- 在每个文件中,单词 BOAT_TODO 添加和删除的次数。
解决方案
您可以使用以下命令执行此操作:
git log --grep=PROJECT_BOAT_COMMIT --format=%H | xargs -L1 sh -c 'git diff $0^ $0 | COMMIT="$0" perl -ne '\''if (/^[-+]{3} [ab]\/(.*)/) { printf "%s %s %d %d\n", $ENV{COMMIT}, $n, $x{"-"}, $x{"+"} if $n && $n ne $1; $n=$1;} $x{$1}++ if /^([-+]).*BOAT_TODO/; END{ printf "%s %s %d %d\n", $ENV{COMMIT}, $n, $x{"-"}, $x{"+"}; }'\'''
本质上,它在提交消息中使用 PROJECT_BOAT_COMMIT 迭代每个提交,打印哈希,然后调用git diff
命令并过滤输出以查找引入文件名或包含添加或删除的“BOAT_TOOD”的行,并将输出打印在表格<commit> <filename> <removals> <additions>
。
那是一个命令,这就是您所要求的,尽管它不是特别漂亮。我已将其格式化为下面的 shell 脚本,以防更具吸引力。如果你更喜欢 Perl 以外的东西,你也可以使用不同的脚本语言,但是 Perl 在 Git 所在的所有系统上都可用,所以我选择了它以防你使用 Windows。如果您在文件名中使用空格或类似的东西,您可以调整它。
最后,如果你想避免一堆(虽然不是全部)没有添加或删除的行,你可以添加参数-G BOAT_TODO
,这将限制 Git 只打印那些包含“BOAT_TODO”的提交。否则,它将打印包含“PROJECT_BOAT_COMMIT”的所有提交的数据,无论该提交是否包含“BOAT_TODO”的任何实例。
如果您正在寻找简单而优雅的东西,我很抱歉;Git 并没有提供一种简单而优雅的方式来做你想做的事,而脚本绝对是实现你目标的 Git 方式。
#!/bin/sh
git log --grep=PROJECT_BOAT_COMMIT --format=%H | \
xargs -L1 sh -c '
git diff $0^ $0 | \
COMMIT="$0" perl -n -e '\''if (/^[-+]{3} [ab]\/(.*)/) {
printf "%s %s %d %d\n", $ENV{COMMIT}, $n, $x{"-"}, $x{"+"} if $n && $n ne $1;
$n=$1;
}
$x{$1}++ if /^([-+]).*BOAT_TODO/;
END {
printf "%s %s %d %d\n", $ENV{COMMIT}, $n, $x{"-"}, $x{"+"};
}
'\'''
推荐阅读
- html - Angular 指令订阅 HTMLInput 上的类属性更改?
- node.js - 压缩十进制如何存储值。如何为变量类型PIC S9(09)V99 COMP-3的压缩十进制编写节点js逻辑
- c# - 发生奇怪的“对象引用未设置为对象的实例”错误
- c# - 如何让程序读取目录中的每个文件夹以及每个文件夹中的每个文件
- java - 用于确定主页部分的清洁架构用例——更新
- r - 如何在分类变量条形图中添加“总计”?
- snakemake - 与字符串不匹配的通配符约束
- python - 您将如何在 Assembly 中有效地重写此 python 代码
- javascript - 在 Node js 中作为待处理的 Promise
- python - Python如何在1个窗口而不是2个窗口中显示