2516 Stimmen

Wie kann man einen verlorenen Stash in Git wiederherstellen?

Ich verwende häufig git stash y git stash pop um Änderungen in meinem Arbeitsbaum zu speichern und wiederherzustellen. Gestern hatte ich einige Änderungen in meinem Arbeitsbaum, die ich zwischengespeichert und wiederhergestellt habe, und dann habe ich weitere Änderungen an meinem Arbeitsbaum vorgenommen. Ich würde gerne zurückgehen und die gestern gespeicherten Änderungen überprüfen, aber git stash pop scheint alle Verweise auf die zugehörige Übertragung zu entfernen.

Ich weiß, dass ich, wenn ich die git stash dann .git/refs/stash enthält die Referenz der Übergabe, die zur Erstellung des Stash verwendet wurde. Und .git/logs/refs/stash enthält den gesamten Vorrat. Aber diese Referenzen sind verschwunden, nachdem git stash pop . Ich weiß, dass der Commit noch irgendwo in meinem Repository ist, aber ich weiß nicht, was er war.

Gibt es eine einfache Möglichkeit, die gestrige Stash-Commit-Referenz wiederherzustellen?

Für mich ist das heute nicht so wichtig, weil ich tägliche Backups habe und auf den Arbeitsbaum von gestern zurückgreifen kann, um meine Änderungen zu erhalten. Ich frage, weil es einen einfacheren Weg geben muss!

101voto

Greg Hewgill Punkte 882617

Ich habe gerade einen Befehl erstellt, der mir geholfen hat, mein verlorenes Versteck zu finden:

for ref in `find .git/objects | sed -e 's#.git/objects/##' | grep / | tr -d /`; do if [ `git cat-file -t $ref` = "commit" ]; then git show --summary $ref; fi; done | less

Dieser listet alle Objekte im .git/objects-Baum auf, findet die Objekte vom Typ Commit und zeigt dann eine Zusammenfassung jedes einzelnen an. Von da an war es nur noch eine Frage der Zeit, bis ich die Commits durchgesehen hatte, um einen passenden "WIP on work: 6a9bb2" zu finden ("work" ist mein Zweig, 619bb2 ist ein neuer Commit).

Ich stelle fest, dass ich dieses Problem nicht habe, wenn ich "git stash apply" anstelle von "git stash pop" verwende, und wenn ich "git stash save" verwende Nachricht ", dann wäre die Übergabe vielleicht leichter zu finden gewesen.

Update: Mit Nathans Idee wird dies kürzer:

for ref in `git fsck --unreachable | grep commit | cut -d' ' -f3`; do git show --summary $ref; done | less

60voto

Nathan Jones Punkte 5676

git fsck --unreachable | grep commit sollte den sha1 anzeigen, auch wenn die Liste, die es zurückgibt, ziemlich groß sein kann. git show <sha1> zeigt an, ob es sich um die gewünschte Übergabe handelt.

git cherry-pick -m 1 <sha1> fügt die Übertragung in den aktuellen Zweig ein.

51voto

Colin Hebert Punkte 88407

Wenn Sie ein verlorenes Versteck wiederfinden wollen, müssen Sie zuerst den Hash des verlorenen Verstecks finden.

Wie Aristoteles Pagaltzis vorschlug, sollte ein git fsck sollte Ihnen helfen.

Ich persönlich benutze meine log-all Alias, der mir jeden Commit (wiederherstellbare Commits) anzeigt, um einen besseren Überblick über die Situation zu haben:

git log --graph --decorate --pretty=oneline --abbrev-commit --all $(git fsck --no-reflogs | grep commit | cut -d' ' -f3)

Eine noch schnellere Suche ist möglich, wenn Sie nur nach "WIP on"-Meldungen suchen.

Sobald Sie Ihr sha1 kennen, ändern Sie einfach Ihren Vorrat reflog, um den alten Vorrat hinzuzufügen:

git update-ref refs/stash ed6721d

Sie werden es wahrscheinlich vorziehen, eine zugehörige Nachricht zu haben, damit eine -m

git update-ref -m "$(git log -1 --pretty=format:'%s' ed6721d)" refs/stash ed6721d

Und Sie werden dies sogar als Alias verwenden wollen:

restash = !git update-ref -m $(git log -1 --pretty=format:'%s' $1) refs/stash $1

31voto

Adrian W Punkte 3888

Mein Favorit ist dieser Einzeiler:

git log --oneline  $( git fsck --no-reflogs | awk '/dangling commit/ {print $3}' )

Dies ist im Grunde die gleiche Idee wie diese Antwort aber viel kürzer. Natürlich können Sie immer noch hinzufügen --graph um eine baumartige Darstellung zu erhalten.

Wenn Sie die Übergabe in der Liste gefunden haben, wenden Sie sie mit

git stash apply THE_COMMIT_HASH_FOUND

Für mich ist die Verwendung von --no-reflogs den Eintrag über das verlorene Versteck aufgedeckt hat, aber --unreachable (wie in vielen anderen Antworten zu finden) nicht.

Führen Sie es mit git bash aus, wenn Sie unter Windows arbeiten.

Credits: Die Einzelheiten der oben genannten Befehle sind entnommen aus https://gist.github.com/joseluisq/7f0f1402f05c45bac10814a9e38f81bf

24voto

Shaheen Ghiassy Punkte 6977

Ich mochte Aristoteles' Ansatz, aber ich mochte es nicht, GITK zu benutzen... da ich es gewohnt bin, GIT von der Kommandozeile aus zu benutzen.

Stattdessen nahm ich die "Dangling Commits" und gab den Code in eine DIFF-Datei aus, um ihn in meinem Code-Editor zu überprüfen.

git show $( git fsck --no-reflog | awk '/dangling commit/ {print $3}' ) > ~/stash_recovery.diff

Jetzt können Sie die resultierende diff/txt-Datei (die sich in Ihrem Home-Ordner befindet) in Ihren txt-Editor laden und den tatsächlichen Code und das resultierende SHA sehen.

Dann verwenden Sie einfach

git stash apply ad38abbf76e26c803b27a6079348192d32f52219

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X