Zeigt nur relevante Hunks eines Diff / Patches an, der auf einem regulären Ausdruck basiert

20

git log -G<regex> -pist ein wunderbares Werkzeug, um den Verlauf einer Codebasis nach Änderungen zu durchsuchen, die dem angegebenen Muster entsprechen. Es kann jedoch überwältigend sein, das relevante Stück in der Diff / Patch-Ausgabe in einem Meer von größtenteils irrelevanten Stücken zu lokalisieren.

Es ist natürlich möglich, die Ausgabe von git lognach der ursprünglichen Zeichenfolge / Regex zu durchsuchen , aber dies trägt wenig dazu bei, das visuelle Rauschen und die Ablenkung vieler nicht zusammenhängender Änderungen zu verringern.

Beim Nachlesen git logsehe ich --pickaxe-all, dass es das genaue Gegenteil von dem gibt, was ich möchte: Es erweitert die Ausgabe (auf den gesamten Änderungssatz), während ich sie beschränken möchte (auf den bestimmten Teil).

Im Grunde bin ich auf der Suche nach einer Möglichkeit, das Diff / Patch "intelligent" in einzelne Hunks zu zerlegen und dann eine Suche für jeden Hunk durchzuführen (nur auf die geänderten Zeilen abzielen), die nicht übereinstimmenden Hunks zu verwerfen und die auszugeben das tun.

Gibt es ein Tool wie ich es beschreibe? Gibt es einen besseren Ansatz, um die passenden / betroffenen Kerle zu finden?

Erste Recherchen, die ich gemacht habe ...

  • Wenn es möglich wäre, grepdie Diff- / Patch-Ausgabe zu ändern und die Kontextoptionswerte dynamisch zu gestalten, z. B. über reguläre Ausdrücke anstelle von Zeilenzahlen, könnte dies ausreichen. Ist grepaber nicht genau so aufgebaut (und fordere diese Funktion auch nicht unbedingt an).

  • Ich fand die Patchutils- Suite, die anfangs so klang, als würde sie meinen Bedürfnissen entsprechen. Nach dem Lesen der manSeiten scheinen die Tools jedoch keine passenden Hunks zu verarbeiten, die auf regulären Ausdrücken basieren. (Sie können jedoch eine Liste von Kerlen akzeptieren ...)

  • Ich bin schließlich auf splitpatch.rb gestoßen , das das Parsen des Patches gut zu handhaben scheint, aber es müsste erheblich erweitert werden, um das Lesen von Patches über stdin, das Zuordnen gewünschter Hunks und das anschließende Ausgeben der Hunks zu handhaben .

wrksprfct
quelle
1
Nicht genau das, was Sie gefragt haben, aber versuchen Sie es mit git log -Gfoo | weniger + / foo
James Youngman

Antworten:

7

Hier wird unter /programming//a/35434714/5305907 beschrieben, wie Sie das tun können, wonach Sie suchen. effektiv:

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

Es werden nur die Hunks angezeigt, die mit der angegebenen Zeichenfolge "console" übereinstimmen.

Nagu
quelle
Vielen Dank. grepdiffist im Grunde das, was ich will; Ich muss seine Hunk-Matching-Option verpasst haben! Allerdings wird die Git-Commit-Information von entfernt. grepdiffWenn Sie also den entsprechenden Block gefunden haben, müssen Sie das Commit-Sha vom Objekt / Blob-Sha im Diff-Header ableiten - eine ziemlich teure Operation. (siehe stackoverflow.com/a/223890/2284440 ) Es wäre so etwas wiegit find-object SHA --reverse | head -1 | cut -c 1-7 | { read sha ; git log -1 $sha; }
wrksprfct
Beachten Sie auch, dass es eine Golang-Version gibt,grepdiff die mehr Barebones in Bezug auf akzeptierte Argumente bietet. Beachten Sie, dass, wenn das übereinstimmende Stück das letzte Stück in einem Diff ist, es fälschlicherweise den Git-Commit-Header des folgenden Commits enthält - etwas, das mich völlig verwirrte, bis ich realisierte, was los ist!
Wrksprfct
0

Nicht genau das, wonach Sie fragen, aber eine Möglichkeit, durch Hunks zu blättern, ist der interaktive Add-Modus. Dies erfordert, dass Sie das Commit nach dem Patch, an dem Sie interessiert sind, auschecken

git checkout COMMIT_ID

Gehen Sie dann im VCS noch einen Schritt zurück, jedoch nicht im Arbeitsverzeichnis

git reset --soft HEAD^

(An dieser Stelle entspricht der Unterschied zwischen dem Index und dem Arbeitsverzeichnis dem Patch, an dem Sie interessiert sind.)

Sie können jetzt ausführen git add -p. Dies startet eine interaktive Sitzung mit einer /Option, mit der Sie nach Hunks suchen können, in denen einige Zeilen mit einem regulären Ausdruck übereinstimmen. Besonders nützlich, wenn Sie diese Patches tatsächlich weiterverarbeiten möchten (wie das Vorbereiten eines Teil-Cherry-Pick).

Leider funktioniert der /Befehl im add -pMoment nur innerhalb einer einzelnen Datei, so dass Sie möglicherweise mehrere nicht relevante Dateien überspringen müssen.

links herum
quelle
0

Aufbauend auf der obigen Antwort von @nagu und den anderen verknüpften Antworten konnte ich git log -Gnur die relevanten Hunks anzeigen.

  1. Erstelle zuerst irgendwo in deinem $ PATH ein Skript mit folgendem Inhalt:

    #!/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. Rufen git log -GSie Git auf und weisen Sie ihn an, das pickaxe-diffSkript als externen Diff-Treiber zu verwenden:

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

    Dabei wird das Skript pickaxe-diff nur zum Generieren der Diffs verwendet, sodass der Rest der git logAusgabe (Commit-Hash, Nachricht usw.) unberührt bleibt.

Vorsichtsmaßnahme
Die Arbeitsweise der Git-Spitzhacke besteht darin, dass sie die Ausgabe auf die Dateien beschränkt, deren Hunks die angegebene Zeichenfolge / Regex ändern. Dies bedeutet, dass, wenn ein anderer Block in diesen Dateien auch die Suchzeichenfolge / Regex enthält, diese jedoch nicht ändert, diese weiterhin mit dem obigen Skript angezeigt wird. Dies ist eine Einschränkung von grepdiff. Es gibt eine Open Pull-Anforderung im Patchutils-Projekt, um grepdiff ein --only-matchingFlag hinzuzufügen, das die erforderliche Funktionalität zum korrekten Herausfiltern dieser Hunks bietet.


Ich habe meine Lösung in diesem Kern geschrieben .

philb
quelle