it-swarm.com.de

Wie grep (Suche) festgeschriebenen Code in der Git-Geschichte?

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

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

git log -p | grep <pattern>

Dies gibt jedoch den Commit-Hash nicht sofort zurück. Ich habe vergeblich mit git grep herumgespielt.

1302
Ortwin Gentz

Um nach commit content (d. H. Tatsächlichen Quellenzeilen im Gegensatz zu Commit-Nachrichten und dergleichen) zu suchen, müssen Sie Folgendes tun:

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

git rev-list --all | xargs git grep <expression> funktioniert, wenn der Fehler "Argumentliste zu lang" auftritt.

Wenn Sie die Suche auf einen Teilbaum beschränken möchten (z. B. "lib/util"), müssen Sie dies auch dem Unterbefehl rev-list und grep übergeben:

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

Dies durchsucht Ihren gesamten Festschreibungstext nach regexp.

Der Grund für die Übergabe des Pfads in beiden Befehlen ist, dass rev-list die Revisionsliste zurückgibt, in der alle Änderungen an lib/util stattgefunden haben. Sie müssen jedoch auch an grep übergeben, damit dies nur der Fall ist suche in lib/util.

Stellen Sie sich folgendes Szenario vor: grep findet möglicherweise den gleichen <regexp> in anderen Dateien, die in derselben von rev-list zurückgegebenen Revision enthalten sind (auch wenn in dieser Revision keine Änderung an dieser Datei vorgenommen wurde) ).

Hier sind einige andere nützliche Möglichkeiten zum Durchsuchen Ihrer Quelle:

Durchsuchen Sie den Arbeitsbaum nach Text, der mit regulären Ausdrücken in regulären Ausdrücken übereinstimmt:

git grep <regexp>

Durchsuchen Sie den Arbeitsbaum nach Textzeilen, die dem regulären Ausdruck regexp1 oder regexp2 entsprechen:

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

Durchsuchen Sie den Arbeitsbaum nach Textzeilen, die mit regulären Ausdrücken regexp1 und regexp2 übereinstimmen, und geben Sie nur Dateipfade an:

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

Durchsuchen Sie den Arbeitsbaum nach Dateien, deren Textzeilen mit regulären Ausdrücken regexp1 und deren Textzeilen mit regulären Ausdrücken regexp2 übereinstimmen:

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

Durchsuchen Sie den Arbeitsbaum nach geänderten Textzeilen mit passendem Muster:

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

Durchsuchen Sie alle Revisionen nach Text, der mit regulären Ausdrücken in regulären Ausdrücken übereinstimmt:

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

Durchsuchen Sie alle Revisionen zwischen Rev1 und Rev2 nach Text, der mit regulären Ausdrücken in regulären Ausdrücken übereinstimmt:

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

Sie sollten die Option Spitzhacke (_-S_ von git log verwenden

So suchen Sie nach Foo:

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

Weitere Informationen finden Sie unter Git-Verlauf - Suche nach verlorenen Zeilen nach Schlüsselwörtern .


As Jakub Narębski kommentierte:

  • dies sucht nach Unterschieden, die eine Instanz von _<string>_ einführen oder entfernen.
    Es bedeutet normalerweise "Überarbeitungen, bei denen Sie eine Zeile mit 'Foo' hinzugefügt oder entfernt haben".

  • mit der Option _--pickaxe-regex_ können Sie erweiterten POSIX-regulären Ausdruck verwenden, anstatt nach einer Zeichenfolge zu suchen.


Wie Rob kommentiert, wird bei dieser Suche zwischen Groß- und Kleinschreibung unterschieden. Er öffnete eine Folgefrage zur Suche nach Groß- und Kleinschreibung.

496
VonC

Am liebsten mache ich das mit der Option _git log-G_ (hinzugefügt in Version 1.7.4).

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

Es gibt einen subtilen Unterschied zwischen der Art und Weise, wie die Optionen _-G_ und _-S_ bestimmen, ob ein Commit übereinstimmt:

  • Die Option _-S_ zählt im Wesentlichen, wie oft Ihre Suche vor und nach einem Commit mit einer Datei übereinstimmt. Das Festschreiben wird im Protokoll angezeigt, wenn die Anzahl vor und nach dem Festschreiben unterschiedlich ist. Dies zeigt beispielsweise keine Commits an, bei denen eine Ihrer Suche entsprechende Zeile verschoben wurde.
  • Mit der Option _-G_ wird das Commit 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 diesem Festschreiben gleich ist, stimmt die Angabe mit _-Shello_ nicht überein. Da sich jedoch eine Zeile geändert hat, die hello entspricht, wird das Festschreiben mit _-Ghello_ angezeigt.

228
Tyler Holien

Wenn Sie nach Codeänderungen suchen möchten (sehen Sie, was sich mit dem angegebenen Wort im gesamten Verlauf tatsächlich geändert hat), wählen Sie den 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 ;) )
46
Bartek Skwira

Ich nahm @ Jeets Antwort und fügte es Windows hinzu (dank diese Antwort ):

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

Beachten Sie, dass für mich aus irgendeinem Grund das eigentliche Commit, das diesen regulären Ausdruck löschte, nicht in der Ausgabe des Befehls angezeigt wurde, sondern ein Commit davor.

24
ripper234

git log kann eine effektivere Methode für die Suche nach Text in allen Zweigen sein, insbesondere wenn es viele Übereinstimmungen gibt und Sie zuerst die neuesten (relevanten) Ä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 die angegebene Suchzeichenfolge/Regex hinzufügen oder entfernen, (im Allgemeinen) die aktuellste zuerst. Die Option -p bewirkt, dass das relevante Diff dort angezeigt wird, wo das Muster hinzugefügt oder entfernt wurde, damit Sie es im Kontext sehen können.

Nachdem Sie einen relevanten Commit gefunden haben, der den gesuchten Text hinzufügt (z. B. 8beeff00d), suchen Sie die Zweige, die den Commit enthalten:

git branch -a --contains 8beeff00d
20
Edward Anderson

Suche in jede Revision, jede Datei:

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

Suchen Sie nur in bestimmten Dateien nach Beispiel XML-Dateien:

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

Die Ergebniszeilen sollten folgendermaßen aussehen: 6988bec26b1503d45eb0b2e8a4364afb87dde7af: bla.xml: Text der gefundenen Zeile ...

Sie können dann mit git show weitere Informationen wie Autor, Datum, Diff abrufen:

git show 6988bec26b1503d45eb0b2e8a4364afb87dde7af
17

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

Hinweis: Mit der Ansicht Suche von Sourcetree können Sie teilweise nach Text suchen. Drücken Sie Ctrl + 3 um zur Suchansicht zu wechseln (oder klicken Sie unten auf die Registerkarte Suchen). Setzen Sie von ganz rechts den Suchtyp auf Dateiänderungen und geben Sie dann die Zeichenfolge ein, nach der Sie suchen möchten. Diese Methode weist im Vergleich zum obigen Befehl die folgenden Einschränkungen auf:

  1. Sourcetree zeigt nur die Commits an, 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.
6
dotNET

Der Einfachheit halber würde ich die Verwendung der GUI vorschlagen: gitk - Der Git-Repository-Browser . Es ist ziemlich flexibel

  1. So suchen Sie nach Code:

    Enter image description here
  2. So durchsuchen Sie Dateien:

    Enter image description here
  3. Natürlich werden auch reguläre Ausdrücke unterstützt:

    Enter image description here

Mit den Auf-/Ab-Pfeilen können Sie durch die Ergebnisse navigieren.

4
watashiSHUN

@ Jeets Antwort funktioniert in PowerShell.

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

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

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

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

Versuchen Sie also, ältere Versionen des Codes zu durchsuchen, um festzustellen, wo zuletzt etwas vorhanden ist?

Wenn ich das tun würde, würde ich wahrscheinlich Git Bisect verwenden. Mit Bisect können Sie eine als funktionierend bekannte Version, eine als fehlerhaft bekannte Version und ein einfaches Skript angeben, mit dem überprüft wird, ob die Version gut oder schlecht ist (in diesem Fall wird mit einem Grep geprüft, ob der gesuchte Code vorhanden ist ). Wird dies ausgeführt, wird festgestellt, wann der Code entfernt wurde.

1
Rob Di Marco
git rev-list --all | xargs -n 5 git grep EXPRESSION

ist eine Tweak to @ Jeet-Lösung, sodass Ergebnisse während der Suche und nicht nur am Ende angezeigt werden (was in einem großen Repository sehr lange dauern kann).

0
laktak

In meinem Fall musste ich ein Short Commit suchen und die aufgelisteten Lösungen funktionierten leider nicht.

Ich habe es geschafft mit: (Ersetze das REGEX Token)

for commit in $(git rev-list --all --abbrev-commit)
do
    if [[ $commit =~ __REGEX__ ]]; then 
        git --no-pager show -s --format='%h %an - %s' $commit
    fi
done
0
user1183098

Szenario: Sie haben Ihren Code mithilfe Ihrer IDE gründlich aufgeräumt. Problem: Das IDE hat mehr aufgeräumt als es sollte und jetzt kompiliert Ihr Code nicht (fehlende Ressourcen usw.)

Lösung:

git grep --cached "text_to_find"

Es findet die Datei, in der "text_to_find" geändert wurde.

Sie können diese Änderung jetzt rückgängig machen und Ihren Code kompilieren.

0
Garytech

Wann immer ich bei dir bin. Ich benutze die folgende Kommandozeile:

git log -S "<words/phrases i am trying to find>" --all --oneline  --graph 

Erläuterung:

  1. git log - Muss ich hier mehr schreiben, zeigt es die Protokolle in chronologischer Reihenfolge.
  2. -S "<words/phrases i am trying to find>" - Zeigt alle Git Commits an, bei denen eine Datei (hinzugefügt/geändert/gelöscht) die Wörter/Phrasen enthält, die ich ohne die Symbole "<>" zu finden versuche.
  3. --all - Durchsetzen und Durchsuchen aller Zweige.
  4. --oneline - Komprimiert das Git-Protokoll in einer Zeile.
  5. --graph - Erzeugt das Diagramm der chronologisch geordneten Commits.
0
psyco