如何反转`git log --grep = <pattern>`或如何显示与模式不匹配的git日志</pattern>

时间:2011-04-09 01:05:40

标签: git git-log

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

git log --grep=<pattern>

如何反转匹配感?

我试图忽略邮件中“碰到版本......”的提交。

编辑:我希望我的最终输出非常详细。例如git log --pretty --stat。因此git log --format=oneline的输出对我不起作用。

8 个答案:

答案 0 :(得分:23)

这可以通过Git 2.4+ (Q2 2015)实现:commit 22dfa8aChristoph Junghans (junghans)

  

log:教--invert-grep选项

     

git log --grep=<string>”仅显示与给定字符串匹配的消息的提交,但有时仅显示 not 具有特定消息的提交(例如“show”我不是FIXUP的提交“)。

     

最初,我们在invert-grep中有grep_opt标记,但因为“git grep --invert-grep”除了与“--files-with-matches”结合使用之外没有意义通过“--files-without-matches”,它被移动到修订结构   让那里的标志更好地表达了该功能的功能。

     

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

--invert-grep
  

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

示例:

我首先使用“音序器”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

如果我想要带 no 音序器的消息:

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

答案 1 :(得分:15)

生成所有提交的列表,减去其日志消息包含违规模式的提交,并将结果提供给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{$_};
}

假设上述其中一项在您的路径中为git-log-vgrep并且具有表格的历史记录

$ git lola
* b0f2a28 (tmp, feature1) D
* 68f87b0 C
* d311c65 B
* a092126 A
| * 83052e6 (HEAD, origin/master, master) Z
| * 90c3d28 Y
| * 4165a42 X
| * 37844cb W
|/  
* 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 </dev/null
83052e62f0dc1c6ddfc1aff3463504a4bf23e3c4 Z

答案 2 :(得分:8)

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

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

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

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

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

最后一件事,如果你想对它进行分页,请使用“less -r”来保持颜色。

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

答案 3 :(得分:1)

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

git log --format=oneline | grep -v `git log --grep="bumped to version" --format="%h"`

答案 4 :(得分:1)

与thebriguy的答案一样,grep也有一个-z选项,使它能够使用空终止字符串而不是行。这就像反转匹配一样简单:

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

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

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可能更好,请参阅How to give a pattern for new line in grep?。虽然grep -P对我来说很好,但我不知道pcregrep是否有-z选项或等效选项。

答案 5 :(得分: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

应该这样做。

答案 6 :(得分:0)

正如VonC所提到的,最好的选择是你可以更新到Git 2.4.0(目前在RC2上)。但即使你不能这样做,也没有理由精心制作脚本。一个(gnu)awk单行应该这样做。 git log具有有用的-z选项,可以通过NUL字符分隔提交,从而可以轻松解析它们:

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

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

答案 7 :(得分:-1)

git log --pretty --stat | grep -v "bumped to version"