Как инвертировать `git log --grep = <pattern>` или Как показать git log, которые не соответствуют шаблону - PullRequest
33 голосов
/ 09 апреля 2011

Я хочу использовать git log, чтобы показать все коммиты, которые не соответствуют заданному шаблону. Я знаю, что могу использовать следующее, чтобы показать все коммиты, которые соответствуют шаблону:

git log --grep=<pattern>

Как инвертировать смысл соответствия?

Я пытаюсь игнорировать коммиты, которые "столкнулись с версией ..." в сообщении.

РЕДАКТИРОВАТЬ: я хочу, чтобы мой окончательный вывод был довольно многословным. например git log --pretty --stat. Поэтому вывод из git log --format=oneline не будет работать для меня.

Ответы [ 8 ]

23 голосов
/ 15 февраля 2015

Это будет возможно с Git 2.4+ (2 квартал 2015 г.) : см. коммит 22dfa8a от Кристоф Джунгс (junghans) :

log: learn --invert-grep option

"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».

--invert-grep

Ограничить вывод коммитов сообщениями, которые не соответствуют шаблону, указанному в --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

Если я хочу сообщения с no sequencer:

> git log -2 --pretty="tformat:%s" --grep=sequencer --invert-grep
Second batch for 2.11
Merge branch 'js/git-gui-commit-gpgsign'
15 голосов
/ 09 апреля 2011

Создайте список всех коммитов, вычтите те, чьи сообщения журнала содержат шаблон с ошибками, и передайте результат в 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{$_};
}

Предполагается, что один из вышеперечисленных находится в вашей переменной PATH как 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
8 голосов
/ 19 октября 2012

Относительно простой метод с большой гибкостью - использовать 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", чтобы сохранить цвета.

EDIT: изменено наиспользуйте -v в awk, чтобы сделать его немного проще.

1 голос
/ 21 сентября 2013

Как и в ответе the the briguy, 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 или эквивалент.

1 голос
/ 09 апреля 2011

получить список всех коммитов, содержащих ваш результат, затем отфильтровать их хэши.

git log --format=oneline | grep -v `git log --grep="bumped to version" --format="%h"`
0 голосов
/ 21 апреля 2015

Как уже упоминалось в 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, которую я оставлю в качестве упражнения для читателя; -).

0 голосов
/ 09 апреля 2011

Насколько я могу судить, это невозможно сделать напрямую с одной командной строкой; вам нужно будет сделать что-то, как предлагает Джастин Лилли, а затем запустить '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

должен сделать трюк.

0 голосов
/ 09 апреля 2011
git log --pretty --stat | grep -v "bumped to version"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...