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!

4083voto

Aristotle Pagaltzis Punkte 106298

Sobald Sie den Hash des abgelegten Stash Commits kennen, können Sie ihn als Stash verwenden:

git stash apply $stash_hash

Oder Sie können einen separaten Zweig dafür erstellen mit

git branch recovered $stash_hash

Danach können Sie mit allen normalen Werkzeugen machen, was Sie wollen. Wenn du fertig bist, bläst du den Ast einfach weg.

Suche nach der Raute

Wenn Sie es gerade erst geknackt haben und das Terminal noch offen ist, werden Sie immer noch den Hash-Wert, der von git stash pop auf dem Bildschirm (Danke, Dolda).

Andernfalls können Sie es unter Linux, Unix oder Git Bash für Windows finden:

git fsck --no-reflog | awk '/dangling commit/ {print $3}'

...oder mit Powershell für Windows:

git fsck --no-reflog | select-string 'dangling commit' | foreach { $_.ToString().Split(" ")[2] }

Dies zeigt Ihnen alle Commits an den Spitzen Ihres Commit-Graphen, die von keinem Branch oder Tag mehr referenziert werden - jeder verlorene Commit, einschließlich aller Stash-Commits, die Sie jemals erstellt haben, wird irgendwo in diesem Graphen zu finden sein.

Der einfachste Weg, den gewünschten Stash-Commit zu finden, ist wahrscheinlich die Übergabe dieser Liste an gitk :

gitk --all $( git fsck --no-reflog | awk '/dangling commit/ {print $3}' )

...oder siehe die Antwort von emragins wenn Sie Powershell für Windows verwenden.

Dadurch wird ein Repository-Browser gestartet, der Ihnen Folgendes anzeigt jede einzelne Übertragung im Repository, die jemals stattgefunden hat unabhängig davon, ob sie erreichbar ist oder nicht.

Sie können ersetzen gitk dort mit etwas wie git log --graph --oneline --decorate wenn Sie ein schönes Diagramm auf der Konsole einer separaten GUI-Anwendung vorziehen.

Um Stash-Commits zu erkennen, suchen Sie nach Commit-Meldungen dieser Form:

        WIP am somebranch : commithash Eine alte Commit-Nachricht

Nota : Die Übergabemeldung wird nur in dieser Form erscheinen (beginnend mit "WIP on"), wenn Sie bei der Übergabe keine Meldung angegeben haben git stash .

837voto

Dolda2000 Punkte 24257

Wenn Sie das Terminal nicht geschlossen haben, sehen Sie sich einfach die Ausgabe von git stash pop und Sie erhalten die Objekt-ID des abgelegten Verstecks. Normalerweise sieht sie so aus:

$ git stash pop
[...]
Dropped refs/stash@{0} (2ca03e22256be97f9e40f08e6d6773c7d41dbfd1)

(Beachten Sie, dass git stash drop ergibt ebenfalls die gleiche Zeile).

Um den Vorrat zurückzubekommen, führen Sie einfach git branch tmp 2cae03e und du bekommst es als Zweig. Um dies in einen Vorrat umzuwandeln, führen Sie aus:

git stash apply tmp
git stash

Als Zweig können Sie ihn auch frei manipulieren, z. B. um ihn herauszupicken oder zusammenzuführen.

310voto

Wade Punkte 3427

Ich wollte nur auf diesen Zusatz zur akzeptierten Lösung hinweisen. Es war mir nicht sofort klar, als ich diese Methode das erste Mal ausprobierte (vielleicht hätte es das sein sollen), aber um den Stash aus dem Hash-Wert anzuwenden, verwenden Sie einfach "git stash apply":

$ git stash apply ad38abbf76e26c803b27a6079348192d32f52219

Als ich Git noch nicht kannte, war mir das nicht klar, und ich habe verschiedene Kombinationen von "git show", "git apply", "patch" usw. ausprobiert.

279voto

Senthil A Kumar Punkte 8878

Um die Liste der Verstecke zu erhalten, die sich noch in Ihrem Repository befinden, aber nicht mehr erreichbar sind:

git fsck --unreachable | grep commit | cut -d" " -f3 | xargs git log --merges --no-walk --grep=WIP

Wenn Sie Ihrem Stash einen Titel gegeben haben, ersetzen Sie "WIP" in -grep=WIP am Ende des Befehls mit einem Teil Ihrer Nachricht, z. B. -grep=Tesselation .

Der Befehl sucht nach "WIP", weil die Standardübertragungsnachricht für einen Vorrat die Form WIP on mybranch: [previous-commit-hash] Message of the previous commit.

108voto

emragins Punkte 3753

Windows PowerShell-Äquivalent mit gitk:

gitk --all $(git fsck --no-reflog | Select-String "(dangling commit )(.*)" | %{ $_.Line.Split(' ')[2] })

Es gibt wahrscheinlich einen effizienteren Weg, dies in einem Rohr zu tun, aber dies erfüllt die Aufgabe.

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