我希望使用git log
来展示所有不符合给定模式的提交记录。我知道可以使用以下命令来展示所有符合模式的提交记录:
git log --grep=<pattern>
如何反转匹配的含义?
我试图忽略提交信息中包含“bumped to version ...”的提交。
编辑:我想要最终输出结果非常详细,例如 git log --pretty --stat
。因此,git log --format=oneline
的输出对我不起作用。
junghans
)提交的commit 22dfa8a:
log
:添加--invert-grep
选项
"
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 not have certain messages (e.g. "show me ones that are not FIXUP commits").Originally, we had the
invert-grep
flag ingrep_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.--invert-grep
Limit the commits output to ones with log message that do not match the pattern specified with
--grep=<pattern>
.
例子:
我首先使用grep命令筛选包含“sequencer”的信息:
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
指定的模式。--author
、--committer
。git log --exclude-author?
"中查看示例。
git -P log -1 --invert-grep
可能会导致段错误:--grep
" 的情况下给 "git log
"(man) 命令同时提供 "--invert-grep
" 和 "--all-match
" 会尝试访问未分配的 grep 模式表达式结构体,这个问题已经在 Git 2.39 (Q4 2022) 中得到了修复。请注意,保留 html 标签。
查看 commit db84376(2022年10月11日)由Ævar Arnfjörð Bjarmason(avar
)提交。
(由Junio C Hamano -- gitster
--在commit 91d3d7e中合并,2022年10月21日)
grep.c
: 将“扩展”替换为“pattern_expression”,
修复段错误报告者:orygaw
签名者:Ævar Arnfjörð Bjarmason
Since 79d3696 ("
git-grep
: boolean expression on pattern matching.", 2006-06-30, Git v1.4.2-rc1 -- merge) the"pattern_expression"
member has been used for complex queries (AND/OR...), with"pattern_list"
being used for the simple OR queries.
Since then we've used both"pattern_expression"
and its associated boolean "extended" member to see if we have a complex expression.Since f41fb66 (revisions API: have release_revisions() release , 2022-04-13, Git v2.37.0-rc0 -- merge listed in batch #8) (revisions API: have
release_revisions()
release"grep_filter",
2022-04-13) we've had a subtle bug relating to that: If we supplied options that were only used for "complex queries", but didn't supply the query itself we'd set"opt->extended",
but would have aNULL
"pattern_expression"
.
As a result these would segfault as we tried to call "free_grep_patterns()
" from"release_revisions()
":git -P log -1 --invert-grep git -P log -1 --all-match
The root cause of this is that we were conflating the state management we needed in "
compile_grep_patterns()
" itself with whether or not we had an"opt->pattern_expression"
later on.In this cases as we're going through "
compile_grep_patterns()
" we have no"opt->pattern_list"
but have"opt->no_body_match"
or"opt->all_match"
.
So we'd set"opt->extended
= 1", but not "return" on"opt->extended"
as that's an "else if" in the same "if" statement.That behavior is intentional and required, as the common case is that we have an
"opt->pattern_list"
that we're about to parse into the"opt->pattern_expression"
.But we don't need to keep track of this "extended" flag beyond the state management in
compile_grep_patterns()
itself.
It needs it, but once we're out of that function we can rely on"opt->pattern_expression"
being non-NULL instead for using these extended patterns.
git log -5 --pretty="tformat:%s" --grep=sequencer
命令:它完全正常。 - VonC--invert-grep=foo
。现在这个命令对我来说已经可以了,但它比我想象中的要不那么有用。如果能够在一个命令中指定“包含这个 AND 不包含这个”,那就更好了。谢谢! - Kent Boogaart生成所有提交记录的列表,从中减去日志消息包含不良模式的记录,然后将结果传递给带有所需选项的 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
加入了你的PATH路径,并且有以下历史记录:
$ 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此时,我们可以使用以下命令获取Z、Y、W和V:
$ git log-vgrep X也可以查看其他分支的记录:
$ git log-vgrep A tmp可以得到D、C、B和V;
$ git log-vgrep C tmp~2..tmp则只会得到D。
git log
的工作原理相同:
$ git log --stdin --no-walk --pretty=oneline </dev/null 83052e62f0dc1c6ddfc1aff3463504a4bf23e3c4 Z
一种相对简单且灵活的方法是使用带有 -z 选项的 git log 然后将其传递给 awk。-z 选项在提交记录之间添加 nulls,因此可以轻松地通过 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 log -z . |perl -ln0e 'print unless /regex/'
- Zac Thompsongit 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'
log -z --color --pretty --stat | \
grep -Pvz '^.....commit.*\nAuthor:.*\nDate:.*\n[\S\s]*?bumped to version[\S\s]*?\n [^ ]'
grep -P
描述为“高度实验性”。也许最好使用使用 libpcre 的 pcregrep
替代它,参见 如何在 grep 中匹配换行符?。虽然 grep -P
对我来说运作良好,但我不知道 pcregrep
是否有 -z 选项或等效选项。pattern = $ 1; shift; git log-z --color“$ @”| grep-vz“$ pattern”| tr'\ 0''\ n'| less-r
- David Sanders获取包含您结果的所有提交列表,然后过滤掉它们的哈希值。
git log --format=oneline | grep -v `git log --grep="bumped to version" --format="%h"`
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
应该可以解决问题。
正如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版本,这留给读者作为练习;-)。
git log --pretty --stat | grep -v "bumped to version"
git log --invert-grep=<pattern>
,该命令应该可以回答你的问题。请参见我下面的答案。 - VonCgit log --grep=<string>
应该在 Git 2.4(2015年第二季度)中发布:https://github.com/git/git/blob/9ab698f4000a736864c41f57fbae1e021ac27799/Documentation/RelNotes/2.4.0.txt#L25-L26 - VonC