web-dev-qa-db-ja.com

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

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

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

git logを確認すると、--pickaxe-allがあることがわかります。これは、私が望むものとは正反対です。出力を(チェンジセット全体に)広げますが、(特定の塊)。

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

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

私が行ったいくつかの初期の研究...

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

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

  • 私はついに splitpatch.rb に遭遇しました。これはパッチの解析をうまく処理するようですが、stdinを介してパッチの読み取りを処理し、目的のハンクに一致させるには、大幅に拡張する必要があります。そして、ハンクを出力します。

20
wrksprfct

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

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

指定された文字列「コンソール」と一致するハンクのみを表示します。

7
nagu

上記の@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 -Gを呼び出して、pickaxe-diffスクリプトを外部差分ドライバーとして使用するようGitに指示します。

    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-matchingフラグをgrepdiffに追加するためのオープンプルリクエストがあります。これにより、これらのハンクを正しく除外するために必要な機能が提供されます。


this Gist で自分の解決策を書き上げました。

0
philb

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

git checkout COMMIT_ID

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

git reset --soft HEAD^

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

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

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

0
leftaroundabout