Как инвертировать 'git log --grep=' или как показать журналы git, которые не соответствуют шаблону
Я хочу использовать git log
показать все коммиты, которые не соответствуют заданному шаблону. Я знаю, что могу использовать следующее, чтобы показать все коммиты, которые соответствуют шаблону:
git log --grep=<pattern>
как мне инвертировать чувство соответствия?
Я пытаюсь игнорировать коммиты ,которые " наткнулись на версию ..."в сообщении.
EDIT: я хочу, чтобы мой конечный результат был довольно подробным. например,git log --pretty --stat
. Итак, вывод из git log --format=oneline
не будет работать для меня.
8 ответов
создать список всех коммитов, вычесть те, чьи сообщения журнала содержат оскорбительный шаблон, и передать результат в git log
с нужными параметрами. На заключительном этапе, несколько вариантов, чтобы git log
удобная:
--stdin
В дополнение к фиксация перечисленные в командной строке, прочитайте их из стандартного ввода.
--no-walk
Показывать только заданные обороты, но не пересекать их предки.
вы можете сделать это с помощью одного конвейера и замены процесса.
#! /bin/bash
if (( $# < 1 )); then
echo >&2 "Usage: 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
если вы не хотите использовать bash, вы можете сделать это с Perl.
#! /usr/bin/env perl
use strict;
use warnings;
no warnings "exec";
sub usage { "Usage: pattern\n" }
sub commits_to_omit {
my($pattern) = @_;
open my $fh, "-|", "git", "log", "--grep=$pattern", "--format=%H", @ARGV
or die ": 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 ": exec: $!";
open my $out, "|-", "git", "log", "--pretty", "--stat", "--stdin", "--no-walk"
or die ": 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
дает просто Д.
одним из ограничений вышеуказанных реализаций является использование шаблона, который соответствует всем коммитам,например, .
или ^
, тогда вы получите голову. Вот как!--7--> работает:
$ git log --stdin --no-walk --pretty=oneline </dev/null 83052e62f0dc1c6ddfc1aff3463504a4bf23e3c4 Z
это будет возможно с Git 2.4+ (Q2 2015): см.совершить 22dfa8a by Кристоф Junghans (junghans
):
log
: teach--invert-grep
опции"
git log --grep=<string>
" показывает только коммиты с сообщениями, которые соответствуют данной строке, но иногда полезно иметь возможность показывать только коммиты, которые делают не есть определенные сообщения (например, "покажите мне те, которые не фиксируют фиксации").первоначально у нас был
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
Если Я хотите сообщения с нет секвенсор:
> git log -2 --pretty="tformat:%s" --grep=sequencer --invert-grep
Second batch for 2.11
Merge branch 'js/git-gui-commit-gpgsign'
относительно простой метод с большой гибкостью-использовать git log с опцией-z, переданной в awk. Опция-z добавляет нули между записями фиксации и поэтому упрощает синтаксический анализ с помощью awk:
git log --color=always -z | awk -v RS=\0
(цвет=всегда требуется, чтобы сохранить окраску, когда выход является трубой). Затем его просто добавить любое логическое выражение, которое вы хотите, которое работает на каждом поле. Например, это будет печатать все записи, где автор электронной почты не от fugly.com и день совершения было воскресенье:
git log --color=always -z | awk -v RS=\0 '!/Author:.*fugly.com>/ && /Date:.* Sun /'
еще одна хорошая вещь - вы можете добавить в любой параметр форматирования или диапазон ревизий в журнал git, и он все еще работает.
последнее, если вы хотите разбить его на страницы, Используйте "less-r", чтобы сохранить цвета.
EDIT: изменено на использование -v в awk, чтобы сделать его немного проще.
получите список всех коммитов, содержащих ваш результат, а затем отфильтруйте их хэши.
git log --format=oneline | grep -v `git log --grep="bumped to version" --format="%h"`
как и в ответе thebriguy, grep также имеет опцию a-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, см. как дать шаблон для новой строки в grep?. Хотя grep -P
отлично работает для меня и я не знаю, если pcregrep
имеет вариант a-z или аналог.
насколько я могу судить, это невозможно сделать непосредственно с помощью одной командной строки; вам нужно будет сделать что-то вроде предложения Джастина Лилли, а затем запустить "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
следует сделать трюк.
как упоминалось VonC, лучшим вариантом является обновление до Git 2.4.0 (который в настоящее время находится на RC2). Но даже если вы не можете этого сделать, нет причин для сложных сценариев. (Gnu) awk one-liner должен это сделать. git log
имеет полезную -z
возможность разделения коммитов нулевым символом, что упрощает их анализ:
git log -z --pretty --stat | awk 'BEGIN{ RS=""; FS="\n\n" } !match(, /<pattern>/)'
Если у вас нет gnu awk, вы, вероятно, должны по крайней мере установить это. Или перенесите этот скрипт на вашу конкретную версию awk, которую я оставляю как упражнение для читателя ;-).