正規表現に基づいてdiff / patchの関連するハンクのみを表示します


20

git log -G<regex> -p指定されたパターンに一致する変更をコードベースの履歴で検索するための素晴らしいツールです。ただし、ほとんど無関係なハンクの海で、diff / patch出力で関連するハンクを見つけるのは圧倒的です。

もちろんgit log、元の文字列/正規表現の出力を検索することは可能ですが、それは視覚的なノイズと多くの無関係な変更の気を散らすものを減らすのにほとんど役立ちません。

を読むとgit log、があります--pickaxe-all。これは、私が望むものとは正反対です。出力を(チェンジセット全体に)広げる一方で、(特定の塊に)制限したいのです。

基本的に、私は差分/パッチを個々のハンクに「インテリジェントに」解析し、各ハンクに対して検索を実行し(変更された行のみを対象とする)、一致しないハンクを破棄し、それらを出力する方法を探していますそうする。

説明したようなツールは存在しますか?マッチした/影響を受けたハンクを取得するためのより良いアプローチはありますか?

私がやったいくつかの初期調査...

  • grepdiff / patchの出力が可能で、コンテキストオプションの値を動的にすると(たとえば、行数ではなく正規表現を使用して)十分な場合があります。しかしgrep、そのように正確に構築されているわけではありません(また、必ずしもその機能を要求しているわけでもありません)。

  • patchutilsスイートを見つけましたが、当初は自分のニーズに合っているように聞こえました。しかし、そのmanページを読んだ後、ツールは正規表現に基づいて一致するハンクを処理していないようです。(ただし、ハンクのリストを受け入れることができます...)

  • 私はついにsplitpatch.rbに出会いました。これはパッチの解析をうまく処理しているようですが、経由stdinでパッチの読み込みを処理するために大幅に増強する必要があります。


1
あなたが尋ねたものを正確にではなく、git log -Gfoo | less + / foo
ジェームズヤングマン

回答:


7

ここ/programming//a/35434714/5305907は、あなたが探していることを行う方法を説明しています。効果的に:

git diff -U1 | grepdiff 'console' --output-matching=hunk

指定された文字列「console」に一致するハンクのみが表示されます。


ありがとう。grepdiff基本的に私が欲しいものです。ハンクマッチングオプションを見逃したに違いない!ただし、 ...によってgitコミット情報が削除されるgrepdiffため、関連するハンクを見つけたら、diffヘッダー内のオブジェクト/ブロブshaからコミットshaを取得する必要があります。これは非常に高価な操作です。(stackoverflow.com/a/223890/2284440を参照)次のようになりますgit find-object SHA --reverse | head -1 | cut -c 1-7 | { read sha ; git log -1 $sha; }
-wrksprfct

また、受け入れられた引数の点でより骨の折れgrepdiffgolangバージョンがあることに注意してください。マッチしたハンクがdiffの最後のハンクである場合、次のコミットのgitコミットヘッダーが誤って含まれていることに注意してください。
wrksprfct

0

まさにあなたが求めているものではありませんが、ハンクを介してgrepする1つの方法は、インタラクティブな追加モードです。これには、関心のあるパッチの後にコミットをチェックアウトする必要があります

git checkout COMMIT_ID

次に、VCSのもう1つのステップに戻りますが、作業ディレクトリには戻りません

git reset --soft HEAD^

(この時点で、インデックスと作業ディレクトリの違いは、関心のあるパッチに対応します。)

これで実行できgit add -pます。これにより、インタラクティブセッションが起動されます。このセッションでは、/一部の行が正規表現に一致するハンクを見つけることができます。これらのパッチを実際にさらに処理する場合(部分的なチェリーピックの準備など)に特に便利です。

残念ながら、少なくとも現時点では、/コマンドはadd -p単一のファイル内でのみ機能するため、いくつかの無関係なファイルをスキップする必要がある場合があります。


0

@naguによる上記の回答と他のリンクされた回答に基づいて、git log -G関連するハンクのみを表示することができました。

  1. まず、次のコンテンツを使用して$ PATHのどこかにスクリプトを作成します。

    #!/bin/bash
    
    # pickaxe-diff : external diff driver for Git.
    #                To be used with the pickaxe options (git [log|show|diff[.*] [-S|-G])
    #                to only show hunks containing the searched string/regex.
    
    path=$1
    old_file=$2
    old_hex=$3
    old_mode=$4
    new_file=$5
    new_hex=$6
    new_mode=$7
    
    filtered_diff=$(diff -u -p $old_file $new_file | \
                    grepdiff "$GREPDIFF_REGEX" --output-matching=hunk | \
                    grep -v -e '+++ ' -e '--- ')
    
    a_path="a/$path"
    b_path="b/$path"
    
    echo "diff --git $a_path $b_path"
    echo "index $old_hex..$new_hex $old_mode"
    echo "--- $a_path"
    echo "+++ $b_path"
    echo "$filtered_diff"
  2. git log -GGitを呼び出して、pickaxe-diffスクリプトを外部diffドライバーとして使用するように指示します。

    export GREPDIFF_REGEX=<string>; 
    GIT_EXTERNAL_DIFF=pickaxe-diff git log -p --ext-diff -G $GREPDIFF_REGEX

    これは、diffを生成するためだけにpickaxe-diffスクリプトを使用するため、残りのgit log出力(コミットハッシュ、メッセージなど)は変更されません。

警告
Gitのつるはしが機能する方法は、指定された文字列/正規表現を変更するハンクを持つファイルに出力を制限することです。これは、これらのファイルの別のハンクにも検索文字列/正規表現が含まれているが、変更されていない場合、上記のスクリプトで表示されることを意味します。これはgrepdiffの制限です。patchutilsプロジェクトには、--only-matchinggrepdiffにフラグを追加するためのオープンプルリクエストがあります。これにより、これらのハンクを正しくフィルタリングするために必要な機能が提供されます。


この要点で解決策をまとめました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.