生成所有提交的列表,减去那些日志消息包含违规模式的提交,然后将结果提供给git log,并提供您想要的选项。在最后阶段,git log 的几个选项很方便:
--stdin
除了命令行中列出的 commit 之外,从标准输入中读取它们。
--no-walk
只显示给定的转速,但不遍历它们的祖先。
您可以使用单个管道和流程替换来做到这一点。
#! /bin/bash
if (( $# < 1 )); then
echo >&2 "Usage: $0 pattern [<since>..<until>]"
exit 1
fi
pattern=$1
shift
git log --format=%H $@ |
grep -v -f <(git log --format=%H "--grep=$pattern" $@) |
git log --pretty --stat --stdin --no-walk
如果您不想使用 bash,可以使用 Perl。
#! /usr/bin/env perl
use strict;
use warnings;
no warnings "exec";
sub usage { "Usage: $0 pattern\n" }
sub commits_to_omit {
my($pattern) = @_;
open my $fh, "-|", "git", "log", "--grep=$pattern", "--format=%H", @ARGV
or die "$0: exec: $!";
my %omit = map +($_ => 1), <$fh>;
%omit;
}
die usage unless @ARGV >= 1;
my $pattern = shift;
my %omit = commits_to_omit $pattern;
open my $all, "-|", "git", "log", "--format=%H", @ARGV
or die "$0: exec: $!";
open my $out, "|-", "git", "log", "--pretty", "--stat", "--stdin", "--no-walk"
or die "$0: exec: $!";
while (<$all>) {
print $out $_ unless $omit{$_};
}
假设上述之一在您的 PATH 中为 git-log-vgrep 并且具有表单的历史记录
$ git lola
* b0f2a28 (tmp, feature1) D
* 68f87b0 C
* d311c65 B
* a092126 A
| * 83052e6 (HEAD, origin/master, master) Z
| * 90c3d28 是
| * 4165a42 X
| * 37844cb 瓦
|/
* f8ba9ea V
我们可以说
$ git log-vgrep X
得到 Z、Y、W 和 V。
你也可以登录其他分支,所以
$ git log-vgrep A tmp
给出 D、C、B 和 V;和
$ git log-vgrep C tmp~2..tmp
只产生 D。
上述实现的一个限制是,如果您使用匹配所有提交的模式,例如、. 或^,那么您将获得 HEAD。这就是git log 的工作原理:
$ git log --stdin --no-walk --pretty=oneline /null
83052e62f0dc1c6ddfc1aff3463504a4bf23e3c4 Z