Git: Gelöschten Code finden

76

Das macht mich verrückt.

Wie finde ich gelöschten Code?

Am Ende fand ich heraus, wo es damit erstellt wurde:

$ git log --pretty=oneline -S'some code'

Und das ist gut genug, aber ich war auch neugierig zu finden, wo es gelöscht wurde, und bisher keine Würfel.

Zuerst habe ich versucht git diff HEAD..HEAD^|grep 'some code', den Bereich jedes Mal zu erweitern, bis ich die Linien gefunden habe, in denen er entfernt wurde. Schön, also nimm an, ich habe es in Reichweite gefunden HEAD^^..HEAD^^^, dann tue ich es git show HEAD^^^und git show HEAD^^mit grep, aber der Code ist nirgends zu finden!

Dann habe ich ein bisschen nachgelesen git bisect, und sicher gibt es mir eine einzige Revision, in der der Täter sein soll ... Wieder git show rev|grep 'some code'kommt leer ...

Was zum? Was mache ich falsch?

Vielen Dank!

Ivan
quelle
2
Wollen Sie damit sagen, dass Sie im Grunde genommen keine Treffer erhalten, wenn Sie Folgendes tun?: <pre> SHAHIT = `git log --pretty = oneline -S'some code '| Kopf -1 | awk '{print $ 1}' `git show $ SHAHIT | grep 'some code' </ pre> Wenn ja, scheint es unsinnig ... wenn es in ist log, sollte es in show... sichtbar sein, oder? Oder vielleicht verstehe ich die Frage falsch.
Metasim
Es ist schon eine Weile her, seit ich in dieser Situation war und es hat sich nicht wieder gezeigt, also kann ich Ihren Befehl nicht testen. Trotzdem danke, es kann für jemanden nützlich sein.
Ivan
1
Alter Beitrag / Kommentar hier, aber genau das, was ich trotzdem brauchte. @SimeonFitch Ihre Syntax hat bei mir perfekt funktioniert, um die fraglichen Codezeilen zu finden und aufzulisten. Eine Ergänzung, die ich nützlich fand, war die Verwendung der grep-Option '--context = n', um vorher / nachher genügend Zeilen anzuzeigen, um zu wissen, wie der Dateiname auch lautet (es gibt auch andere grep-Optionen, die dabei helfen würden). In meinem Fall war der zweite Befehl: git show $ SHAHIT | grep --context = 30 'irgendein Code'
Dave Marley

Antworten:

57

Hmph, arbeitet für mich:

$ git init
Initialisiertes leeres Git-Repository in /Users/pknotz/foo/.git/

$ echo "Hallo"> a

$ git add a

$ git commit -am "anfängliches Festschreiben"
[master (root-commit) 7e52a51] anfängliches Commit
 1 Dateien geändert, 1 Einfügungen (+), 0 Löschungen (-)
 Erstellungsmodus 100644 a

$ echo "Welt" >> a

$ git commit -am "Sei genauer"
[master 080e9fe] Seien Sie genauer
 1 Dateien geändert, 1 Einfügungen (+), 0 Löschungen (-)

$ echo "Hallo"> a

$ git commit -am "Sei weniger spezifisch"
[master 00f3fd0] Seien Sie weniger spezifisch
 1 Dateien geändert, 0 Einfügungen (+), 1 Löschungen (-)

$ cat a
Hallo

$ git log -SWorld
Commit 00f3fd0134d0d54aafbb9d959666efc5fd492b4f
Autor: Pat Notz <[email protected]>
Datum: Di 6. Oktober 17:20:48 2009 -0600

    Sei weniger spezifisch

Commit 080e9fe84ff89aab9d9d51fb5d8d59e8f663ee7f
Autor: Pat Notz <[email protected]>
Datum: Di 6. Oktober 17:20:33 2009 -0600

    Sei genauer

Oder meinst du das nicht?

Pat Notz
quelle
1
Das meine ich ... Wenn es bei mir nicht funktioniert, kann es sein, dass der Index beschädigt ist oder der Verlauf neu geschrieben wurde?
Ivan
4
In diesem Beispiel verwendet Pat, git log -SWorlddas die Unterschiede nicht anzeigt. Ich vermute (habe es nicht ausprobiert), dass Sie mit dem letzten Befehl git show 00f3fd0134d0d54aafbb9d959666efc5fd492b4f | grep Worlddas Verhalten erhalten würden, nach dem Sie suchen.
Metasim
2
Dies kann nicht die akzeptierte Antwort sein, da es nicht nur die Frage nicht beantwortet, sondern auch nur ein "Werk für mich" ist
Dionysius
45

git log -S<string>erledigt den Job, aber wenn Sie komplexere Suchvorgänge durchführen müssen, können Sie verwenden git log -G<regex>.

Aus dem man:

-G<regex>

Suchen Sie nach Unterschieden, deren Patch-Text übereinstimmende hinzugefügte / entfernte Zeilen enthält <regex>.

Simone
quelle
1

Ich habe Ihre Frage gefunden, als ich selbst verrückt geworden bin, und bisher war keine Antwort ausreichend. Ich habe einen Weg gefunden, um das spezifische Commit zu finden, aber es wird nur angezeigt, wenn zwischen diesen Commits unterschieden wird. Ich kann nicht erklären, warum Git so funktioniert, aber ich werde meine Ergebnisse näher erläutern:


Problem erklärt

Mit '-S' oder '-G' können wir nur finden, wo es hinzugefügt und nicht entfernt wurde. Um näher darauf einzugehen:

$ git log --format="%H" -S"127.0.124.1"
857aa361293abbb351d6d6becaa55ec011aebc93
$ git show 857aa361293abbb351d6d6becaa55ec011aebc93 | grep "127.0.124.1" # remove grep to see full diff
+       return "127.0.124.1", nil

Schritt für Schritt

Ich habe die Idee von miku86 auf dev.to . Zuerst versuchen wir, das letzte Commit zu finden, bei dem unsere Zeichenfolge vorhanden war:

$ git --no-pager grep "127.0.124.1" $(git rev-list --all) # | head -n1 | cut -d: -f1 # uncomment to only show the hash of the first one
ba0b2d348f4e33857c96acf5a6231cf9d89ddb1b:some/file.go:        return "127.0.124.1"
0d19a98d6434da0b4b5cc2bac190b9b1de36d992:some/file.go:        return "127.0.124.1"
84274c5712bacbbee1dca5567cef77a2b6f356d2:some/file.go:        return "127.0.124.1"
42e692643ff8a5dce7a89e985062b3d38c60fcc0:some/file.go:        return "127.0.124.1"

Das Ergebnis ba0b2d348f4e33857c96acf5a6231cf9d89ddb1bist unser gesuchtes Commit. Als nächstes versuchen wir, das folgende Commit bis HEAD zu finden:

$ git rev-list ba0b2d348f4e33857c96acf5a6231cf9d89ddb1b.. # | tail -n1 # uncomment to only show the last one
[...]
c82d040f7be2f8955075655843400a36ceb75303
aa0568b543db57564770d73e736aaf50fd749fb4
dde61dae0cf648e7f4dd8a5c194bcf9be1745793

Das ist dde61dae0cf648e7f4dd8a5c194bcf9be1745793, da dies der letzte in dieser Liste ist, den wir suchen.

Das heißt also, dde61dae0cf648e7f4dd8a5c194bcf9be1745793sollte diese Entfernung enthalten sein?

$ git show dde61dae0cf648e7f4dd8a5c194bcf9be1745793 | grep "127.0.124.1" # remove grep to see full diff
#<no output>

Nein?!? Nun, was ist dann der Unterschied zu unserem ersten gefundenen Commit?

$ git diff ba0b2d348f4e33857c96acf5a6231cf9d89ddb1b..dde61dae0cf648e7f4dd8a5c194bcf9be1745793 | grep "127.0.124.1" # remove grep to see full diff
-       return "127.0.124.1"

Hier haben wir es gefunden. Das ist seltsam. Aber da wir einen Unterschied zwischen Commits verwenden, habe ich einen Fehler gemacht und es gibt andere Commits dazwischen?

$ git log --pretty=oneline ba0b2d348f4e33857c96acf5a6231cf9d89ddb1b..dde61dae0cf648e7f4dd8a5c194bcf9be1745793
dde61dae0cf648e7f4dd8a5c194bcf9be1745793 network interface

Nein, wir scheinen keinen Fehler gemacht zu haben. Das ist seltsam. Aber ja, so weit bin ich gekommen, um die Stelle zu finden, an der die Saite verschwunden ist.


zusätzlich

Ich kann bestätigen, git bisectdass dies dde61dae0cf648e7f4dd8a5c194bcf9be1745793das Commit ist, nach dem ich gesucht habe.

# bisecting a while...
$ git bisect bad 
dde61dae0cf648e7f4dd8a5c194bcf9be1745793 is the first bad commit
commit dde61dae0cf648e7f4dd8a5c194bcf9be1745793
Author: ...
Date:   Fri Oct 18 11:04:26 2019 +0200

    network interface

:100644 100644 242e81c363c2c7069efb018821821553b98f2c97 416c27f5351a9d92a6914b34846c6de51d83dd0d M      go.mod
:040000 040000 715c3ab5b3f4579d8054618f1e11fc05fb425324 e6731408a1ac1ff0428128ccbb1fbfaad4c789ab M      network
[...]
Dionysius
quelle
Beachten Sie, dass dies git --no-pager grep "127.0.124.1" $(git rev-list --all)nur funktioniert, wenn Sie eine relativ kleine Anzahl von Commits haben, andernfalls haben Sie einen Bash-Fehler 'Argumentliste zu lang'
simpleuser