Wie grep Git Git Commit Diffs oder Inhalte für ein bestimmtes Wort?

622

In einem Git-Code-Repository möchte ich alle Commits auflisten, die ein bestimmtes Wort enthalten. Ich habe es versucht

git log -p | grep --context=4 "word"

Aber es gibt mir nicht unbedingt den Dateinamen zurück (es sei denn, es ist weniger als 5 Zeilen von dem Wort entfernt, nach dem ich gesucht habe. Ich habe es auch versucht

git grep "word"

aber es gibt mir nur aktuelle Dateien und nicht die Geschichte.

Wie durchsuche ich den gesamten Verlauf, um Änderungen an einem bestimmten Wort zu verfolgen? Ich beabsichtige, meine Codebasis nach Vorkommen von Wörtern zu durchsuchen, um Änderungen aufzuspüren (Suche im Dateiverlauf).

Jesper Rønn-Jensen
quelle

Antworten:

905

Wenn Sie alle Commits suchen möchten, bei denen die Commit-Nachricht ein bestimmtes Wort enthält, verwenden Sie

$ git log --grep=word

Wenn Sie alle Commits finden möchten, bei denen "Wort" im Dateiinhalt hinzugefügt oder entfernt wurde (genauer gesagt: wo sich die Anzahl der Vorkommen von "Wort" geändert hat), dh den Commit-Inhalt durchsuchen , verwenden Sie die sogenannte "Spitzhacke" -Suche mit

$ git log -Sword

Im modernen Git gibt es auch

$ git log -Gword

um nach Unterschieden zu suchen, deren hinzugefügte oder entfernte Zeile mit "Wort" übereinstimmt (auch Inhalte festschreiben ).

Beachten Sie, dass -Gstandardmäßig eine Regex akzeptiert wird, während -Seine Zeichenfolge akzeptiert wird. Sie kann jedoch geändert werden, um Regexe mit der zu akzeptieren --pickaxe-regex.

Um den Unterschied zwischen -S<regex> --pickaxe-regexund zu veranschaulichen -G<regex>, betrachten Sie ein Commit mit dem folgenden Unterschied in derselben Datei:

+    return !regexec(regexp, two->ptr, 1, &regmatch, 0);
...
-    hit = !regexec(regexp, mf2.ptr, 1, &regmatch, 0);

While git log -G"regexec\(regexp"zeigt dieses Commit an, git log -S"regexec\(regexp" --pickaxe-regexwird es jedoch nicht (da sich die Anzahl der Vorkommen dieser Zeichenfolge nicht geändert hat).


Mit Git 2.25.1 (Februar 2020) wird die Dokumentation zu diesen regulären Ausdrücken geklärt.

Siehe Commit 9299f84 (06. Februar 2020) von Martin Ågren (``) .
(Zusammengeführt von Junio ​​C Hamano - gitster- in Commit 0d11410 , 12. Februar 2020)

diff-options.txt: Vermeiden Sie im Beispiel "Regex" -Überlastung

Berichtet von: Adam Dinwoodie
Unterzeichnet von: Martin Ågren
Bewertet von: Taylor Blau

Wenn wir den Unterschied zwischen -Gund -S(using --pickaxe-regex) veranschaulichen , verwenden wir dazu ein Beispiel diff undgit diff Aufruf mit "regexec", "regexp", "regmatch", ...

Das Beispiel ist richtig, aber wir können das Entwirren erleichtern, indem wir vermeiden, "Regex. *" Zu schreiben, es sei denn, es ist wirklich notwendig, um unseren Standpunkt zu verdeutlichen.

Verwenden Sie stattdessen einige erfundene, nicht reguläre Wörter.

Die git diffDokumentation enthält jetzt:

Um den Unterschied zwischen -S<regex> --pickaxe-regexund zu veranschaulichen -G<regex>, betrachten Sie ein Commit mit dem folgenden Unterschied in derselben Datei:

+    return frotz(nitfol, two->ptr, 1, 0);
...
-    hit = frotz(nitfol, mf2.ptr, 1, 0);

While git log -G"frotz\(nitfol"zeigt dieses Commit an, git log -S"frotz\(nitfol" --pickaxe-regexwird es jedoch nicht (da sich die Anzahl der Vorkommen dieser Zeichenfolge nicht geändert hat).

Jakub Narębski
quelle
3
@TankorSmash -S<string>Suchen Sie nach Unterschieden, die eine Instanz von <string> einführen oder entfernen. -G<string>Suchen Sie nach Unterschieden, deren hinzugefügte oder entfernte Zeile mit dem angegebenen <regex> übereinstimmt.
m-ric
1
@ m-ric Oh, ich verstehe, eine einzelne String-Instanz im Vergleich zu einer ganzen Zeile! Danke
TankorSmash
3
@ m-ric, @TankorSmash: Der Unterschied besteht darin, dass er -S<string>schneller ist, da nur geprüft wird, ob die Anzahl der Vorkommen <string>geändert wurde, während -G<string>in jedem Commit-Diff eine Zeile hinzugefügt und entfernt wird.
Jakub Narębski
3
Wenn Sie Wörter mit Leerzeichen dazwischen suchen müssen , git log --grep="my words".
MEM
4
@MEM --grepunterscheidet sich von -Sund -G. Sie können die Zeichenfolge zu jedem dieser Argumente zitieren.
Acumenus
255

git logDie Spitzhacke findet Commits mit Änderungen, einschließlich "Wort" mit git log -Sword

u0b34a0f6ae
quelle
60
Dies ist nicht ganz genau. -S <string> Suchen Sie nach Unterschieden, die eine Instanz von <string> einführen oder entfernen. Beachten Sie, dass dies anders ist als die Zeichenfolge, die einfach in der Diff-Ausgabe angezeigt wird.
Tymtam
4
Obwohl dies im Allgemeinen die richtige Antwort ist, habe ich nur herabgestimmt, um andere zu ermutigen, diese Antwort ( stackoverflow.com/a/1340245/586983 ) zu lesen, die drei verschiedene Möglichkeiten hat und deren Feinheiten erklärt.
Jakeonrails
18
Meine Güte! Ich denke nicht, dass dies ein guter Grund ist, eine richtige Antwort abzulehnen ... Sie waren sich nicht sicher, ob das Einfügen des Links in einen Kommentar eine ausreichende Ermutigung wäre?
Deborah
@jakeonrails, Diese Antwort hätte eine Bearbeitung dieser (älteren) sein sollen, also haben wir diese nervigen Duplikate nicht. Aber die Leute wollen nur den Ruf, anstatt eine saubere Antwortseite.
Iulian Onofrei
22

Nach vielen Experimenten kann ich Folgendes empfehlen, das Commits zeigt, die Zeilen mit einem bestimmten regulären Ausdruck einführen oder entfernen, und die Textänderungen in jedem anzeigt, wobei die Farben die hinzugefügten und entfernten Wörter anzeigen.

git log --pickaxe-regex -p --color-words -S "<regexp to search for>"

Es dauert eine Weile, bis ich renne ... ;-)

CharlesW
quelle
2
Dies ist einer der besten, danke. Tipp: GIT_PAGER=cat| cat
Zack Morris
Geben Sie einen Pfad oder eine Datei an, die viel schneller istgit log --pickaxe-regex -p --color-words -S "<regexp to search for>" <file or fiepath>
fangxing
10

Sie können den folgenden Befehl versuchen:

git log --patch --color=always | less +/searching_string

oder grepauf folgende Weise verwenden:

git rev-list --all | GIT_PAGER=cat xargs git grep 'search_string'

Führen Sie diesen Befehl in dem übergeordneten Verzeichnis aus, in dem Sie suchen möchten.

Kenorb
quelle
2
Ich mag diese Methode, weil die Commits, die ich betrachte, Hunderte von Zeilen mit nicht zusammenhängenden Änderungen enthalten und ich nur an den tatsächlichen Patches interessiert bin, die das gesuchte Wort enthalten. Um Farbe zu bekommen git log --patch --color=always | less +/searching_string.
Radon Rosborough
9

Eine weitere Möglichkeit / Syntax dazu ist: So git log -S "word"
können Sie beispielsweise suchengit log -S "with whitespaces and stuff @/#ü !"

1u-
quelle
1

vim-fugitive ist vielseitig für diese Art der Prüfung in Vim.

Verwenden Sie :Ggrepdazu. Für weitere Informationen können Sie vim-fugitive installieren und das Turorial von nachschlagen :help Grep. Und diese Episode: Das Erkunden der Geschichte eines Git-Repositorys wird Sie dazu führen, all das zu tun.

Lerner Zhang
quelle
1

So verwenden Sie den booleschen Konnektor für reguläre Ausdrücke:

git log --grep '[0-9]*\|[a-z]*'

Diese Suche nach regulären Ausdrücken sucht nach regulären Ausdrücken [0-9] * oder [az] * für Festschreibungsnachrichten.

Reudismam
quelle
-1

Wenn Sie nach vertraulichen Daten suchen möchten, um sie aus Ihrem Git-Verlauf zu entfernen (weshalb ich hier gelandet bin), gibt es dafür Tools. Github als spezielle Hilfeseite für dieses Problem .

Hier ist der Kern des Artikels:

Der BFG Repo-Cleaner ist eine schnellere und einfachere Alternative zum Git-Filter-Zweig zum Entfernen unerwünschter Daten. Führen Sie beispielsweise Folgendes aus, um Ihre Datei mit vertraulichen Daten zu entfernen und Ihr letztes Commit unberührt zu lassen:

bfg --delete-files YOUR-FILE-WITH-SENSITIVE-DATA

Führen Sie Folgendes aus, um den gesamten in passwords.txt aufgeführten Text zu ersetzen, wo immer er sich im Verlauf Ihres Repositorys befindet.

bfg --replace-text passwords.txt

Anweisungen zur vollständigen Verwendung und zum Herunterladen finden Sie in der Dokumentation des BFG Repo-Cleaner .

edelans
quelle
Vielleicht möchten Sie diese Antwort zu stackoverflow.com/questions/872565/… hinzufügen, anstatt hier
lacostenycoder