web-dev-qa-db-ja.com

`git log --grep = <pattern>`を反転する方法またはパターンと一致しないgitログを表示する方法

git logを使用して、特定のパターンに一致しないすべてのコミットを表示したいと思います。以下を使用して、パターンに一致するすべてのコミットを表示できることを知っています。

git log --grep=<pattern>

マッチングの感覚を逆にするにはどうすればよいですか?

メッセージ内の「バージョンにバンプ...」されているコミットを無視しようとしています。

編集:最終出力をかなり冗長にしたい。例えばgit log --pretty --stat。したがって、git log --format=onelineからの出力は私には機能しません。

33
saltycrane

すべてのコミットのリストを生成し、ログメッセージに問題のあるパターンが含まれているコミットを差し引き、必要なオプションを使用して結果を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 [。 * 83052e6(HEAD、オリジン/マスター、マスター)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を生成します。

上記の実装の制限の1つは、すべてのコミットに一致するパターンを使用する場合、e.g。.、または^の場合、HEADを取得することです。 git logの仕組みは次のとおりです。

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

これは Git 2.4+(Q2 2015) で可能になります: commit 22dfa8a by Christoph Junghans(junghans :を参照してください。

log--invert-grepオプションを教える

git log --grep=<string>」は、指定された文字列に一致するメッセージを含むコミットのみを表示しますが、notに特定のメッセージを含まないコミットのみを表示できると便利な場合があります(例:「FIXUPコミットではないものを表示してください」)。

元々、invert-grepgrep_optフラグがありましたが、「git grep --invert-grep」は、すでに「--files-with-matches」でカバーされている「--files-without-matches」との組み合わせ以外では意味がないため、リビジョン構造に移動されました。
フラグを付けることで、機能をより適切に表現できます。

新しく挿入された2つのテストが実行されると、履歴にはメッセージ「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'
23
VonC

柔軟性の高い比較的単純な方法は、awkにパイプされた-zオプションを指定してgitlogを使用することです。 -zオプションは、コミットレコード間にnullを追加するため、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 /'

もう1つの優れた点は、任意のフォーマットオプションまたはリビジョン範囲をgitログに追加でき、それでも機能することです。

最後に、ページ付けする場合は、「less-r」を使用して色を保持します。

編集:awkで-vを使用するように変更して、少し簡単にしました。

8
thebriguy

Thebriguyの回答と同様に、grepにも-zオプションがあり、行ではなくnullで終了する文字列を処理できるようになっています。これは、一致を反転するのと同じくらい簡単です。

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は、私のマニュアルページで「非常に実験的」と説明されています。 libpcreを使用する代わりにpcregrepを使用する方が良い場合があります。 grepで改行のパターンを指定する方法は? を参照してください。 grep -Pは私にとっては問題なく動作し、pcregrepに-zオプションまたは同等のものがあるかどうかはわかりません。

1
Graeme

結果を含むすべてのコミットのリストを取得し、それらのハッシュをフィルターで除外します。

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

私の知る限り、これを1つのコマンドラインで直接実行することはできません。 Justin Lillyが提案するようなことをしてから、結果のハッシュリストで「gitlog」を実行する必要があります。

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
ebneter

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
David Ongaro