Frage Wie grep (suchen) Sie den Code in der git-Historie?


Ich habe in der Vergangenheit eine Datei oder einen Code in einer Datei gelöscht. Kann ich den Inhalt grep (nicht in den Commit-Nachrichten)?

Eine sehr schlechte Lösung ist, das Protokoll zu grep:

git log -p | grep <pattern>

Allerdings gibt dies den Commit-Hash nicht sofort zurück. Ich habe mit herumgespielt git grep umsonst.


1112
2018-05-28 11:36


Ursprung


Antworten:


Nach Commit suchen Inhalt (d. h. tatsächliche Zeilen der Quelle, im Gegensatz zu Commit-Nachrichten und dergleichen), was Sie tun müssen, ist:

git grep <regexp> $(git rev-list --all)

Aktualisierung: git rev-list --all | xargs git grep expression funktioniert, wenn Sie auf einen Fehler "Argumentliste zu lang" stoßen

Wenn Sie die Suche auf einen Teilbaum beschränken möchten (zum Beispiel "lib / util"), müssen Sie dies an die rev-list Unterbefehl und grep auch:

git grep <regexp> $(git rev-list --all -- lib/util) -- lib/util

Dadurch wird der gesamte Commit-Text für regexp durchsucht.

Der Grund für das Übergeben des Pfades in beiden Befehlen ist, weil rev-list gibt die Revisionsliste zurück, in der alle Änderungen enthalten sind lib/util passiert ist, aber auch du musst vorbeikommen grep damit es nur weiter sucht lib/util.

Stellen Sie sich das folgende Szenario vor: grep könnte das gleiche finden <regexp> auf anderen Dateien, die in der gleichen Revision enthalten sind, die von zurückgegeben wird rev-list (auch wenn diese Datei in dieser Revision nicht geändert wurde).

Hier sind einige andere nützliche Möglichkeiten, um Ihre Quelle zu suchen:

Arbeitsbaum für Text suchen, der regulärem Ausdruck regexp entspricht:

git grep <regexp>

Suchen Sie im Arbeitsbaum nach Textzeilen, die mit dem regulären Ausdruck regexp1 oder regexp2 übereinstimmen:

git grep -e <regexp1> [--or] -e <regexp2>

Suchen Sie nach dem Arbeitsbaum für Textzeilen, die mit dem regulären Ausdruck regexp1 und regexp2 übereinstimmen und nur Dateipfade melden:

git grep -e <regexp1> --and -e <regexp2>

Arbeitsbaum für Dateien suchen, die Textzeilen enthalten, die dem regulären Ausdruck regexp1 und Textzeilen entsprechen, die dem regulären Ausdruck regexp2 entsprechen:

git grep -l --all-match -e <regexp1> -e <regexp2>

Suchfunktionsbaum nach geänderten Textzeilen, die mit dem Muster übereinstimmen:

git diff --unified=0 | grep <pattern>

Durchsuche alle Revisionen nach Text, der regulärem Ausdruck regexp entspricht:

git grep <regexp> $(git rev-list --all)

Durchsuche alle Revisionen zwischen rev1 und rev2 nach Text, der regulärem Ausdruck regexp entspricht:

git grep <regexp> $(git rev-list <rev1>..<rev2>)

1483
2018-05-28 13:47



Du solltest das benutzen Spitzhacke (-S) Option von git log

Suchen nach Foo:

git log -SFoo -- path_containing_change 
git log -SFoo --since=2009.1.1 --until=2010.1.1 -- path_containing_change

Sehen Git history - finde die verlorene Zeile nach Schlüsselwort für mehr.


Wie Jakub Narębski kommentiert:

  • Dies sucht nach Unterschieden, die eine Instanz von hinzufügen oder entfernen <string>.
    Es bedeutet normalerweise "Revisionen, wo Sie mit" Foo "hinzugefügt oder entfernt haben.

  • das --pickaxe-regex Option ermöglicht es Ihnen, erweiterte POSIX-Regex zu verwenden, anstatt nach einer Zeichenfolge zu suchen.


Wie rauben kommentiert, diese Suche ist Groß-und Kleinschreibung - er öffnete eine Zusatzfrage wie man die Groß- und Kleinschreibung nicht beachtet.


439
2018-05-28 11:57



Meine Lieblingsbeschäftigung ist mit git logist es -G Option (hinzugefügt in Version 1.7.4).

-G<regex>
       Look for differences whose added or removed line matches the given <regex>.

Es gibt einen feinen Unterschied zwischen dem -G und -S Optionen bestimmen, ob ein Commit übereinstimmt:

  • Das -S Die Option zählt im Wesentlichen die Häufigkeit, mit der Ihre Suche in einer Datei vor und nach einem Commit übereinstimmt. Das Commit wird im Protokoll angezeigt, wenn die Vorher- und Nachher-Anzahl unterschiedlich ist. Dies zeigt beispielsweise keine Commits an, bei denen eine zu Ihrer Suche passende Zeile verschoben wurde.
  • Mit dem -G Wenn diese Option gefunden wird, wird die Festschreibung im Protokoll angezeigt, wenn Ihre Suche mit einer Zeile übereinstimmt, die hinzugefügt, entfernt oder geändert wurde.

Nehmen Sie dieses Commit als Beispiel:

diff --git a/test b/test
index dddc242..60a8ba6 100644
--- a/test
+++ b/test
@@ -1 +1 @@
-hello hello
+hello goodbye hello

Da die Häufigkeit, mit der "Hallo" in der Datei angezeigt wird, vor und nach dem Festschreiben gleich ist, stimmt die Verwendung nicht überein -Shello. Da es jedoch zu einer Zeilenanpassung eine Änderung gab hellowird das Commit mit angezeigt -Ghello.


204
2017-09-14 18:34



Wenn Sie Code-Änderungen durchsuchen möchten (siehe, was tatsächlich mit dem gegebenen Wort in der gesamten Historie geändert wurde), gehen Sie nach patch Modus - Ich habe eine sehr nützliche Kombination gefunden:

git log -p
# hit '/' for search mode
# type in the word you are searching
# if the first search is not relevant hit 'n' for next (like in vim ;) )

33
2018-04-17 08:17



ich nahm @ Jeets Antwort und an Windows angepasst (danke an diese Antwort):

FOR /F %x IN ('"git rev-list --all"') DO @git grep <regex> %x > out.txt

Beachten Sie, dass das eigentliche Commit, das diesen Regex gelöscht hat, aus irgendeinem Grund nicht in der Ausgabe des Befehls, sondern nur vor einem Commit angezeigt wurde.


22
2017-11-17 09:35



Suchen in jede Revision, irgendwelche Dateien:

git rev-list --all | xargs git grep <regexp>

Suche nur in bestimmten Dateien, zum Beispiel XML-Dateien:

git rev-list --all | xargs -I{} git grep <regexp> {} -- "*.xml"

Die Ergebniszeilen sollten wie folgt aussehen: 6988bec26b1503d45eb0b2e8a4364afb87dde7af: bla.xml: Text der gefundenen Zeile ...

Sie können dann weitere Informationen wie Autor, Datum, Diff mit Git-Show erhalten:

git show 6988bec26b1503d45eb0b2e8a4364afb87dde7af

10
2018-04-02 15:03



git log Dies kann eine effektivere Möglichkeit sein, nach Text in allen Zweigen zu suchen, besonders wenn es viele Übereinstimmungen gibt und Sie zuerst neuere (relevante) Änderungen sehen möchten.

git log -p --all -S 'search string'
git log -p --all -G 'match regular expression'

Diese Protokollbefehle listen Commits auf, die den angegebenen Suchstring / regex (in der Regel aktueller) zuerst hinzufügen oder entfernen. Das -p Die Option bewirkt, dass das relevante diff angezeigt wird, wo das Muster hinzugefügt oder entfernt wurde, sodass Sie es im Kontext sehen können.

Wenn Sie ein relevantes Commit gefunden haben, das den gesuchten Text hinzufügt (zB 8beeff00d), suchen Sie nach den Zweigen, die das Commit enthalten:

git branch -a --contains 8beeff00d

8
2018-06-23 00:38



Für alle anderen, die das versuchen SourceTreeIn der Benutzeroberfläche gibt es dafür keinen direkten Befehl (ab Version 1.6.21.0). Sie können jedoch die in der angenommenen Antwort angegebenen Befehle verwenden, indem Sie öffnen Terminal Fenster (Schaltfläche in der Hauptsymbolleiste verfügbar) und kopieren / einfügen sie darin.

Hinweis: SourceTree's Suche View kann teilweise Text für Sie suchen. Drücken Sie Strg + 3 um zur Suchansicht zu gelangen (oder klicken Sie auf die Registerkarte Suche, die am unteren Rand verfügbar ist). Stellen Sie von ganz rechts den Suchtyp auf ein Dateiänderungen und geben Sie dann die Zeichenfolge ein, die Sie durchsuchen möchten. Diese Methode hat folgende Einschränkungen im Vergleich zum obigen Befehl:

  1. SourceTree zeigt nur die verpflichtet die das Suchwort in einer der geänderten Dateien enthalten. Das Finden der genauen Datei, die den Suchtext enthält, ist wiederum eine manuelle Aufgabe.
  2. RegEx wird nicht unterstützt.

5
2017-10-01 05:51



Versuchen Sie also, ältere Versionen des Codes zu durchsuchen, um zu sehen, wo etwas zuletzt existiert?

Wenn ich das machen würde, würde ich wahrscheinlich verwenden Git Halbierung. Mit bisect können Sie eine bekannte gute Version, eine bekannte fehlerhafte Version und ein einfaches Skript angeben, das überprüft, ob die Version gut oder schlecht ist (in diesem Fall ein Grep, um zu sehen, ob der gesuchte Code vorhanden ist) ). Das wird ausgeführt, wenn der Code entfernt wurde.


2
2018-05-28 11:52



@ Jeets Antwort funktioniert in PowerShell.

git grep -n <regex> $(git rev-list --all)

Im Folgenden werden alle Dateien in einem Commit angezeigt, die a enthalten password.

# store intermediate result
$result = git grep -n "password" $(git rev-list --all)

# display unique file names
$result | select -unique { $_ -replace "(^.*?:)|(:.*)", "" }

2
2017-12-16 02:17



Der Einfachheit halber würde ich vorschlagen, GUI zu verwenden: gitk - Der Git-Repository-BrowserEs ist ziemlich flexibel

  1. Code suchen: enter image description here
  2. Datei suchen: enter image description here
  3. Natürlich unterstützt es auch Regex: enter image description here

und Sie können mit den Auf- / Ab-Pfeilen durch die Ergebnisse navigieren


2
2018-02-07 07:35