35

我想用来git log显示与给定模式不匹配的所有提交。我知道我可以使用以下内容来显示所有匹配模式的提交:

git log --grep=<pattern>

如何反转匹配感?

我试图忽略消息中“撞到版本...”的提交。

编辑:我希望我的最终输出非常冗长。例如git log --pretty --stat。所以输出git log --format=oneline对我不起作用。

4

8 回答 8

32

这将通过Git 2.4+(2015 年第二季度)成为可能:请参阅Christoph Junghans的提交 22dfa8ajunghans

log:教学--invert-grep选项

" git log --grep=<string>" 仅显示与给定字符串匹配的消息的提交,但有时能够仅显示没有某些消息的提交很有用(例如,“显示不是 FIXUP 提交的提交”)。

最初,我们将invert-grep标志放在 中grep_opt,但因为“ git grep --invert-grep”除了与“”结合使用之外没有意义--files-with-matches,这已经被“ --files-without-matches”覆盖,因此将其移至修订结构。
在那里有标志可以更好地表达功能的功能。

当新插入的两个测试运行时,历史将有提交的消息“ initial”、“ second”、“ third”、“ fourth”、“ fifth”、“ sixth”和“ Second”,按此顺序提交。与 " " 或 " "
都不匹配的提交是 " " 和 " "。对于不区分大小写的情况,只有“ ”匹配。thSecsecondinitialinitial

--invert-grep

将提交输出限制为具有与指定的模式不匹配的日志消息的提交输出--grep=<pattern>

例子:

我首先在其中包含“sequencer”的 grep 消息:

vonc@voncm C:\Users\vonc\prog\git\git

> git log -2 --pretty="tformat:%s" --grep=sequencer
Merge branch 'js/sequencer-wo-die'
sequencer: ensure to release the lock when we could not read the index

如果我想要没有定序器的消息:

> git log -2 --pretty="tformat:%s" --grep=sequencer --invert-grep
Second batch for 2.11
Merge branch 'js/git-gui-commit-gpgsign'

警告:这只会反转由 指定的模式--grep。从 Git 2.35+(2022 年第一季度)开始,
它将不再反转标头匹配,例如--author, 。请参阅“等价于: ” 中的示例。--committer
git log --exclude-author?

于 2015-02-15T04:47:46.780 回答
16

生成所有提交的列表,减去那些日志消息包含违规模式的提交,然后将结果提供给git log您想要的选项。在最后阶段,有几个选项git log很方便:

--stdin
除了命令行中列出的提交之外,还可以从标准输入中读取它们。

--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并且具有表单的历史记录

$ 混帐萝拉
* 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 一个 tmp

给出 D、C、B 和 V;和

$ git log-vgrep C tmp~2..tmp

只产生 D。

上述实现的一个限制是,如果您使用匹配所有提交的模式,例如.或,^那么您将获得 HEAD。这是如何git log工作的:

$ git log --stdin --no-walk --pretty=oneline </dev/null
83052e62f0dc1c6ddfc1aff3463504a4bf23e3c4 Z
于 2011-04-09T17:02:42.573 回答
8

一个相对简单且具有很大灵活性的方法是使用带有 -z 选项的 git log 通过管道传输到 awk。-z 选项在提交记录之间添加空值,因此可以使用 awk 轻松解析:

git log --color=always -z | awk -v RS=\\0

(当输出为管道时,需要 color=always 保持着色)。然后,添加您想要的适用于每个字段的任何布尔表达式很简单。例如,这将打印作者电子邮件不是来自 fugly.com 的所有条目,并且提交日期是星期日:

git log --color=always -z | awk -v RS=\\0 '!/Author:.*fugly.com>/ && /Date:.* Sun /'

另一个好处是你可以在 git 日志中添加任何格式选项或修订范围,它仍然有效。

最后一件事,如果要对其进行分页,请使用“less -r”来保留颜色。

编辑:更改为在 awk 中使用 -v 以使其更简单一些。

于 2012-10-19T18:44:20.057 回答
1

获取包含您的结果的所有提交的列表,然后过滤掉它们的哈希值。

git log --format=oneline | grep -v `git log --grep="bumped to version" --format="%h"`
于 2011-04-09T01:26:44.397 回答
1

与 thebriguy 的答案一样, grep 也有一个 -z 选项,以使其能够处理以空字符结尾的字符串而不是行。这就像反转匹配一样简单:

git log -z --color | grep -vz "bumped to version"

为了安全起见,您可能只想在提交消息中匹配。要使用 grep 执行此操作,您需要使用珍珠表达式来匹配以空字符结尾的字符串中的换行符。要跳过标题:

git log -z | grep -Pvz '^commit.*\nAuthor:.*\nDate:.*\n[\S\s]*bumped to version'

或颜色:

git log -z --color | \
  grep -Pvz '^.....commit.*\nAuthor:.*\nDate:.*\n[\S\s]*bumped to version'

最后,如果使用 --stat,您还可以匹配此输出的开头以避免匹配包含提交字符串的文件名。因此,该问题的完整答案如下所示:

log -z --color --pretty --stat | \
  grep -Pvz '^.....commit.*\nAuthor:.*\nDate:.*\n[\S\s]*?bumped to version[\S\s]*?\n [^ ]'

请注意,这grep -P在我的手册页中被描述为“高度实验性”。pcregrep使用 libpcre可能会更好,请参阅如何在 grep 中为新行提供模式?. 虽然grep -P对我来说很好,但我不知道是否pcregrep有 -z 选项或等效选项。

于 2013-09-21T11:10:09.140 回答
0

据我所知,这不可能直接用一个命令行来完成。您必须执行 Justin Lilly 建议的操作,然后在生成的哈希列表上运行“git log”,例如,

git log --format="%h" | grep -v `git log -1 --grep="bumped to version" --format="%h"` > good-hashes
for h in `cat good-hashes`; do
    PAGER=cat git log -1 --pretty --stat $h
done

应该做的伎俩。

于 2011-04-09T02:45:24.940 回答
0

正如 VonC 所提到的,最好的选择是您可以更新到 Git 2.4.0(目前在 RC2 上)。但即使你不能这样做,也没有理由编写复杂的脚本。A (gnu) awk one-liner 应该这样做。git log具有通过 NUL 字符分隔提交的有用-z选项,这使得解析它们变得容易:

git log -z --pretty --stat | awk 'BEGIN{ RS="\0"; FS="\n\n" } !match($2, /<pattern>/)'

如果您没有 gnu awk,您可能至少应该安装它。或者将此脚本移植到您的特定 awk 版本,我将其作为练习留给读者 ;-)。

于 2015-04-21T09:11:21.227 回答
-1
git log --pretty --stat | grep -v "bumped to version"
于 2011-04-09T01:39:16.603 回答