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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5602204/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-19 05:19:06  来源:igfitidea点击:

How to invert `git log --grep=<pattern>` or How to show git logs that don't match a pattern

gitgit-log

提问by saltycrane

I want to use git logto show all commits that do not match a given pattern. I know I can use the following to show all commits that do match a pattern:

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

git log --grep=<pattern>

How do I invert the sense of matching?

如何反转匹配感?

I am trying to ignore commits that have "bumped to version ..." in the message.

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

EDIT: I want my final output to be pretty verbose. e.g. git log --pretty --stat. So output from git log --format=onelinewon't work for me.

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

采纳答案by Greg Bacon

Generate a list of all commits, subtract those whose log messages contain the offending pattern, and feed the result to git logwith your desired options. In the final stage, a couple of options to git logare handy:

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

--stdin
In addition to the commitlisted on the command line, read them from the standard input.

--no-walk
Only show the given revs, but do not traverse their ancestors.

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

--no-walk
只显示给定的转速,但不遍历它们的祖先。

You can do it with a single pipeline and process substitution.

您可以使用单个管道和流程替换来完成。

#! /bin/bash

if (( $# < 1 )); then
  echo >&2 "Usage: 
#! /usr/bin/env perl

use strict;
use warnings;
no warnings "exec";

sub usage { "Usage: 
$ 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
pattern\n" } sub commits_to_omit { my($pattern) = @_; open my $fh, "-|", "git", "log", "--grep=$pattern", "--format=%H", @ARGV or die "
$ git log-vgrep X
: 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 "
$ git log-vgrep A tmp
: exec: $!"; open my $out, "|-", "git", "log", "--pretty", "--stat", "--stdin", "--no-walk" or die "
$ git log-vgrep C tmp~2..tmp
: exec: $!"; while (<$all>) { print $out $_ unless $omit{$_}; }
pattern [<since>..<until>]" exit 1 fi pattern= shift git log --format=%H $@ | grep -v -f <(git log --format=%H "--grep=$pattern" $@) | git log --pretty --stat --stdin --no-walk

If you don't want to use bash, you could do it with Perl.

如果你不想使用 bash,你可以用 Perl 来做。

$ git log --stdin --no-walk --pretty=oneline </dev/null
83052e62f0dc1c6ddfc1aff3463504a4bf23e3c4 Z

Assuming one of the above is in your PATH as git-log-vgrepand with a history of the form

假设上述之一在您的 PATH 中,git-log-vgrep并且具有以下形式的历史记录

--invert-grep

we could say

我们可以说

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

to get Z, Y, W, and V.

得到 Z、Y、W 和 V。

You can also log other branches, so

你也可以记录其他分支,所以

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

gives D, C, B, and V; and

给出 D、C、B 和 V;和

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

yields just D.

只产生 D。

One limitation of the above implementations is if you use a pattern that matches all commits, e.g., .or ^, then you'll get HEAD. This is how git logworks:

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

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

回答by VonC

This will be possible with Git 2.4+ (Q2 2015): see commit 22dfa8aby Christoph Junghans (junghans):

这将有可能与Git的2.4及以上(2015年第二季度):见犯22dfa8a克里斯托夫·容汉斯(junghans

log: teach --invert-grepoption

"git log --grep=<string>" shows only commits with messages that match the given string, but sometimes it is useful to be able to show only commits that do nothave certain messages (e.g. "show me ones that are not FIXUP commits").

Originally, we had the invert-grepflag in grep_opt, but because "git grep --invert-grep" does not make sense except in conjunction with "--files-with-matches", which is already covered by "--files-without-matches", it was moved it to revisions structure.
To have the flag there expresses the function to the feature better.

When the newly inserted two tests run, the history would have commits with messages "initial", "second", "third", "fourth", "fifth", "sixth" and "Second", committed in this order.
The commits that does not match either "th" or "Sec" is "second" and "initial". For the case insensitive case only "initial" matches.

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”的提交,按此顺序提交。
与 " th" 或 " Sec"都不匹配的提交是 " second" 和 " initial"。对于不区分大小写的情况,只有 " initial" 匹配。

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

Limit the commits output to ones with log message that do not match the pattern specified with --grep=<pattern>.

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

Example:

例子:

I first grep message with "sequencer" in them:

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

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

If I want messages with nosequencer:

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

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

回答by thebriguy

A relatively simple method with a lot of flexibility is to use git log with the -z option piped to awk. The -z option adds nulls between commit records, and so makes it easy parse with awk:

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

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

(color=always is required to keep coloring when the output is a pipe). Then, its simple to add any boolean expression you want that works on each field. For example, this will print all entries where the author email is not from fugly.com, and the day of the commit was Sunday:

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

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

Another nice thing is its you can add in any formatting option or revision range to the git log, and it still works.

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

One last thing, if you want to paginate it, use "less -r" to keep the colors.

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

EDIT: changed to use -v in awk to make it a little simpler.

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

回答by Graeme

As with thebriguy's answer, grep also has a -z option to enable it to work with null terminated strings rather than lines. This would then be as simple as inverting the match:

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

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

For safety you may want to match within the commit message only. To do this with grep, you need to use pearl expressions to match newlines within the null terminated strings. To skip the header:

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

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

Or with colour:

或颜色:

##代码##

Finally, if using --stat, you could also match the beginning of this output to avoid matching file names containing the commit string. So a full answer to the question would look like:

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

##代码##

Note that grep -Pis described as 'highly experimental' in my man page. It may be better to use pcregrepinstead which uses libpcre, see How to give a pattern for new line in grep?. Although grep -Pworks fine for me and I have no idea if pcregrephas a -z option or equivalent.

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

回答by Justin Abrahms

get a list of all commits containing your result, then filter out their hashes.

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

##代码##

回答by David Ongaro

As mentioned by VonC the best option is if you can update to Git 2.4.0 (which is currently on RC2). But even if you can't do that there is no reason for elaborate scripts. A (gnu) awk one-liner should do it. git loghas the useful -zoption to separate commits by a NUL-character which makes it easy to parse them:

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

##代码##

If you don't have gnu awk, you probably should at least install that. Or port this script to your specific awk version, which I leave as an exercise for the reader ;-).

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

回答by ebneter

As far as I can tell, this is not possible to do directly with a single command line; you'd have to do something like Justin Lilly suggests and then run 'git log' on the resulting list of hashes, e.g.,

据我所知,这是不可能直接使用单个命令行完成的;你必须像 Justin Lilly 建议的那样做一些事情,然后在生成的哈希列表上运行“git log”,例如,

##代码##

should do the trick.

应该做的伎俩。

回答by Spyros

##代码##