wake-up-neo.net

Wie durchsuche ich alle Git- und Mercurial-Commits im Repository nach einer bestimmten Zeichenfolge?

Ich habe ein Git-Repository mit wenigen Verzweigungen und Dangling Commits. Ich möchte alle derartigen Commits im Repository nach einer bestimmten Zeichenfolge durchsuchen.

Ich weiß, wie man ein Protokoll aller Commits in der Geschichte erstellt, aber diese beinhalten keine Zweige oder baumelnden Blobs, sondern nur die Geschichte von HEAD. Ich möchte sie alle dazu bringen, ein bestimmtes Commit zu finden, das verlegt wurde.

Ich würde auch gerne wissen, wie das bei Mercurial geht, da ich über den Wechsel nachdenke.

287
Josip

Sie können baumelnde Commits mit git log -g Sehen.

-g, --walk-reflogs
 Instead of walking the commit ancestry chain, walk reflog entries from
 the most recent one to older ones. 

Auf diese Weise können Sie eine bestimmte Zeichenfolge in einer Commit-Nachricht finden, die baumelt:

git log -g --grep=search_for_this

Wenn Sie die Änderungen nach einer bestimmten Zeichenfolge durchsuchen möchten, können Sie alternativ die Suchoption für die Spitzhacke "-S" verwenden:

git log -g -Ssearch_for_this
# this also works but may be slower, it only shows text-added results
git grep search_for_this $(git log -g --pretty=format:%h)

Git 1.7.4 wird fügen Sie die Option -G hinz , sodass Sie -G <regulärer Ausdruck> übergeben können, um zu ermitteln, wann eine Zeile mit <regulärer Ausdruck> verschoben wurde, was -S nicht kann. -S teilt Ihnen nur mit, wann sich die Gesamtzahl der Zeilen, die die Zeichenfolge enthalten, geändert hat (d. H. Hinzufügen/Entfernen der Zeichenfolge).

Schließlich können Sie gitk verwenden, um die baumelnden Commits zu visualisieren mit:

gitk --all $(git log -g --pretty=format:%h)

Verwenden Sie dann die Suchfunktionen, um nach der falsch platzierten Datei zu suchen. All diese Arbeiten, vorausgesetzt, das fehlende Commit ist nicht "abgelaufen" und der Müll wurde eingesammelt. Dies kann passieren, wenn es 30 Tage lang baumelt und Sie Reflogs ablaufen lassen oder einen Befehl ausführen, der sie abläuft.

327
richq

In Mercurial verwenden Sie hg log --keyword, um nach Stichwörtern in den Commit-Nachrichten zu suchen, und hg log --user, um nach einem bestimmten Benutzer zu suchen. Sehen hg help log für andere Möglichkeiten, das Protokoll einzuschränken.

54
Martin Geisler

Zusätzlich zu richq answer der Verwendung von git log -g --grep=<regexp> Oder git grep -e <regexp> $(git log -g --pretty=format:%h): werfen Sie einen Blick auf die folgenden Blog-Posts von Junio ​​C Hamano, dem aktuellen Betreuer der Git


Zusammenfassung

Beide git grep und git log --grep sind zeilenorientiert , indem sie nach Zeilen suchen, die mit dem angegebenen Muster übereinstimmen.

Sie können git log --grep=<foo> --grep=<bar> (Oder git log --author=<foo> --grep=<bar>, Das intern in zwei --grep Übersetzt wird) verwenden, um Commits zu finden, die entweder von Mustern (implizit ODER semantisch).

Aufgrund der Zeilenorientierung besteht die nützliche UND Semantik darin, git log --all-match --grep=<foo> --grep=<bar> Zu verwenden, um commit) zu finden das hat beide Zeilenanpassung zuerst und Zeilenanpassung zweitens irgendwo.

Mit git grep Können Sie mehrere Muster (alle, die das Formular -e <regexp> Verwenden müssen) mit --or (Das ist die Standardeinstellung), --and Und --not, ( Und ). Für grep bedeutet --all-match, Dass file Zeilen haben muss, die mit jeder der Alternativen übereinstimmen.

22
Jakub Narębski

Aufbauend auf der Antwort von rq habe ich festgestellt, dass diese Zeile das tut, was ich will:

git grep "search for something" $(git log -g --pretty=format:%h -S"search for something")

Welches die Festschreibungs-ID, den Dateinamen und die übereinstimmende Zeile wie folgt ausgeben wird:

91ba969:testFile:this is a test

... Ist jemand damit einverstanden, dass dies eine nette Option wäre, um in den Standard-Befehl git grep aufgenommen zu werden?

11
Sam Hiatt

Jeder Befehl, der Referenzen als Argumente verwendet, akzeptiert das --all Option dokumentiert in der Manpage für git rev-list wie folgt:

   --all
       Pretend as if all the refs in $GIT_DIR/refs/ are listed on the
       command line as <commit>.

Also zum Beispiel git log -Sstring --all zeigt alle Commits an, die string erwähnen und auf die über einen Zweig oder ein Tag zugegriffen werden kann (ich gehe davon aus, dass Ihre Dangling-Commits mindestens mit einem Tag benannt sind).

5
adl

Mit Mercurial machst du a

$ hg grep "search for this" [file...]

Es gibt andere Optionen, die den Bereich der durchsuchten Revisionen einschränken.

5
Yawar

Ich weiß nichts über Git, aber in Mercurial würde ich die Ausgabe von hg log einfach an ein sed/Perl/whatever-Skript leiten, um nach dem zu suchen, wonach Sie suchen. Sie können die Ausgabe von hg log mithilfe einer Vorlage oder eines Stils anpassen, um die Suche zu vereinfachen.

Dies schließt alle benannten Zweige in das Repo ein. Mercurial hat nicht so etwas wie baumelnde Blobs afaik.

2

Um nur eine weitere noch nicht erwähnte Lösung hinzuzufügen, musste ich sagen, dass die Verwendung des grafischen Suchfelds von gitg für mich die einfachste Lösung war. Es wird das erste Vorkommen ausgewählt und Sie können das nächste mit Strg-G finden.

1
icarito

wenn Sie ein vim-Benutzer sind, können Sie tig installieren (apt-get install tig) und denselben Befehl/verwenden, um in vim zu suchen

https://blogs.atlassian.com/2013/05/git-tig/

1
jacktrade

Ein Befehl in git, von dem ich denke, dass es viel einfacher ist, einen String zu finden:

git log --pretty=oneline --grep "string to search"

funktioniert in Git 2.0.4

1
Adriano Rosa