Wie stelle ich einen gelöschten Stash in Git wieder her?

Lesezeit: 8 Minuten

Benutzer-Avatar
Greg Hewgill

benutze ich häufig git stash und git stash pop um Änderungen in meinem Arbeitsbaum zu speichern und wiederherzustellen. Gestern hatte ich einige Änderungen in meinem Arbeitsbaum, die ich gestasht und geknallt hatte, und dann habe ich weitere Änderungen an meinem Arbeitsbaum vorgenommen. Ich würde gerne zurückgehen und die gestrigen Änderungen überprüfen, aber git stash pop scheint alle Verweise auf den zugehörigen Commit zu entfernen.

Ich weiß, dass, wenn ich benutze git stash dann .git/refs/stash enthält die Referenz des Commits, der zum Erstellen des Stashs verwendet wurde. Und .git/logs/refs/stash enthält der ganze Vorrat. Aber diese Referenzen sind verschwunden git stash pop. Ich weiß, dass sich das Commit noch irgendwo in meinem Repository befindet, aber ich weiß nicht, was es war.

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

  • Hinweis für die Zukunft: Wenn Sie nicht jedes Mal Ihre Vorräte verlieren möchten git stash popdu kannst tun git stash apply stattdessen. Es macht dasselbe, außer dass es den Verweis auf den angewendeten Stash nicht entfernt.

    – Kevin

    10. Juli 2013 um 17:12 Uhr

  • Habe hier alles ausprobiert, konnte keinen Stash finden, der bereits gepoppt war. So froh für IntelliJ’s jetbrains.com/help/idea/local-history.html

    – Juan Mendes

    29. Mai 2018 um 12:59 Uhr

  • Siehe auch So stellen Sie gespeicherte, nicht festgeschriebene Änderungen wieder her

    – mfaani

    21. März 2019 um 14:55 Uhr

  • Vorschlag: Vermeiden Sie die Verwendung git stash für alles, was Sie nicht bereit sind zu verlieren. Wenn es sich lohnt zu speichern, dann lohnt es sich, einen vollständigen Commit durchzuführen (möglicherweise in einem separaten temporären Zweig). Mit git commit, Ihre “Verstecke” sind viel einfacher zu verfolgen. Zum einen können Sie eine Commit-Nachricht einfügen. Aber relevanter für diese Frage ist, dass Ihre Änderungen im lokalen Reflog zugänglich sind – selbst wenn Sie den Zweig zurücksetzen/löschen.

    – Brent Bradburn

    27. April um 23:00 Uhr


Benutzer-Avatar
Aristoteles Pagaltzis

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

git stash apply $stash_hash

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

git branch recovered $stash_hash

Danach können Sie mit allen normalen Werkzeugen tun, was Sie wollen. Wenn Sie fertig sind, blasen Sie den Ast einfach weg.

Hash finden

Wenn Sie es gerade erst geknallt haben und das Terminal noch geöffnet ist, wird Ihnen immer noch der Hash-Wert von gedruckt git stash pop auf dem Bildschirm (Danke, Dolda).

Andernfalls können Sie es für 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] }

Dadurch werden Ihnen alle Commits an den Spitzen Ihres Commit-Diagramms angezeigt, auf die von keinem Zweig oder Tag mehr verwiesen wird – jeder verlorene Commit, einschließlich aller Stash-Commits, die Sie jemals erstellt haben, befindet sich irgendwo in diesem Diagramm.

Der einfachste Weg, den gewünschten Stash-Commit zu finden, besteht wahrscheinlich darin, diese Liste an sie weiterzugeben gitk:

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

… oder sehen Sie sich die Antwort von emragins an, wenn Sie PowerShell für Windows verwenden.

Dadurch wird ein Repository-Browser gestartet, der Sie anzeigt jedes einzelne Commit im Repository jemalsunabhängig davon, ob es erreichbar ist oder nicht.

Sie können ersetzen gitk dort mit so etwas wie git log --graph --oneline --decorate wenn Sie eine schöne Grafik auf der Konsole einer separaten GUI-App vorziehen.

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

WIP an irgendein Zweig: commithash Eine alte Commit-Nachricht

Notiz: Die Commit-Nachricht hat nur dann diese Form (beginnend mit “WIP on”), wenn Sie keine Nachricht geliefert haben, als Sie dies getan haben git stash.

  • Jaydel nahm mir die Worte aus dem Mund. Dieser Beitrag hat meinen Job gerettet 🙂 Ich möchte nur hinzufügen – das Erinnern an das Datum, an dem Sie an dem verloren gegangenen gearbeitet haben, macht es einfacher, gitk nach dem zu durchsuchen, wonach Sie suchen.

    – Sridhar Sarnobat

    4. September 2015 um 17:52 Uhr


  • @Codey: Weil PowerShell. Ich weiß nicht, ob MsysGit eine AWK-Binärdatei enthält. Googeln sagt mir, dass so etwas wie %{ $_.Split(' ')[2]; } sollte das Äquivalent von tun {print $3} darin awk Befehl in PowerShell, aber ich habe kein Windows-System, um das zu testen, und Sie brauchen immer noch ein Äquivalent für den /dangling commit/ Teil. Egal, lauf einfach git fsck --no-reflog und schau dir die Ausgabe an. Sie möchten die Hashes aus den Zeilen „dangling commit “.

    – Aristoteles Pagaltzis

    2. Oktober 2015 um 3:55 Uhr

  • Es ist erwähnenswert, dass die Commit-Nachricht nur dann die Zeichenfolge “WIP” enthält, wenn Sie beim Stashing keine eigene Nachricht angegeben haben (d. h. durch Doing git stash save "<message>").

    – Samir Aguiar

    29. Juli 2016 um 1:19 Uhr

  • Wenn Sie wissen, wann der Drop passiert ist, können Sie diesen Einzeiler verwenden, um die Liste der hängenden Commits nach zunehmender Zeit zu erhalten: git fsck --no-reflog | awk '/dangling commit/ {print $3}' | xargs -L 1 git --no-pager show -s --format="%ci %H" | sort Der letzte Eintrag ist wahrscheinlich der, den Sie möchten stash apply.

    – ris8_allo_zen0

    15. Mai 2017 um 9:31 Uhr

  • git stash apply {ref} hat einen fallen gelassenen Vorrat wiederhergestellt! git ist so toll, dass es illegal sein sollte!

    – Tom Russel

    4. November 2017 um 7:32 Uhr


Benutzer-Avatar
Dolda2000

Wenn Sie das Terminal nicht geschlossen haben, sehen Sie sich einfach die Ausgabe von an git stash pop und Sie haben die Objekt-ID des gelöschten Stashs. Normalerweise sieht es so aus:

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

(Beachten Sie, dass git stash drop produziert auch die gleiche Linie.)

Um diesen Vorrat zurückzubekommen, lauf einfach git branch tmp 2cae03e, und Sie erhalten es als Zweig. Um dies in einen Stash zu konvertieren, führen Sie Folgendes aus:

git stash apply tmp
git stash

Wenn Sie es als Zweig haben, können Sie es auch frei manipulieren. zum Beispiel, um es herauszupicken oder zusammenzuführen.

  • Sie können auch tun git stash apply commitid dann git stash um einen neuen Vorrat zu bekommen.

    – Matthäus Flaschen

    23. November 2011 um 20:11 Uhr

  • Beachten Sie, dass wenn git den Stash automatisch zusammenführt und Konflikte hat, es Ihnen den Hash nicht anzeigt.

    – James

    26. September 2013 um 20:53 Uhr

  • @James: Andererseits, wenn diese Konflikte auf das Laufen zurückzuführen sind git stash popes wird den Stash auch nicht fallen lassen, also ist das normalerweise kein Problem.

    – Dolda2000

    27. September 2013 um 3:23 Uhr

  • Es gab kein SHA in meiner Git-Stash-Pop-Ausgabe. 🙁

    – Wegwerfkonto

    19. Oktober 2017 um 16:36 Uhr

  • @MatthewFlaschen Sie können auch den alten Stash wiederherstellen git stash store commitid. Dies hat den Vorteil, dass Ihr Arbeitsverzeichnis nicht angetastet wird und das Datum des ursprünglichen Stashs erhalten bleibt.

    – jakun

    15. Juni 2021 um 6:21 Uhr

Ich wollte nur diese Ergänzung zur akzeptierten Lösung erwähnen. Als ich diese Methode zum ersten Mal ausprobierte, war es mir nicht sofort klar (vielleicht hätte es sein sollen), aber um den Stash aus dem Hash-Wert anzuwenden, verwende einfach “git stash apply “:

$ git stash apply ad38abbf76e26c803b27a6079348192d32f52219

Als ich neu bei Git war, war mir das nicht klar, und ich probierte verschiedene Kombinationen von „git show“, „git apply“, „patch“ usw.

  • Beachten Sie, dass dies den Stash auf den aktuellen Arbeitsbaum anwendet (duh!). Wenn der Baum schmutzig ist, möchten Sie möglicherweise entweder einen temporären Zweig verwenden oder zuerst stashen, den Stash aus dem SHA-1 anwenden, erneut stashen und dann den vorletzten Stash (namens stash@{1}) öffnen.

    – musikk

    24. März 2014 um 10:28 Uhr

Benutzer-Avatar
Senthil A Kumar

So erhalten Sie die Liste der Stashes, 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 Vorrat einen Titel gegeben haben, ersetzen Sie „WIP“ in -grep=WIP am Ende des Befehls mit einem Teil Ihrer Nachricht, z -grep=Tesselation.

Der Befehl sucht nach „WIP“, da die Standard-Commit-Nachricht für einen Stash in der Form vorliegt WIP on mybranch: [previous-commit-hash] Message of the previous commit.

Wenn Sie das Commit gefunden haben, wenden Sie es mit an git stash apply <commit_hash>

Ich habe gerade einen Befehl erstellt, der mir geholfen hat, meinen verlorenen Stash-Commit 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

Dies listet alle Objekte in der .git/objects-Struktur auf, lokalisiert diejenigen, die vom Typ „commit“ sind, und zeigt dann eine Zusammenfassung von jedem an. Von diesem Punkt an war es nur noch eine Frage der Durchsicht der Commits, um ein passendes „WIP on work: 6a9bb2“ zu finden („work“ ist mein Zweig, 619bb2 ist ein neuer Commit).

Ich stelle fest, dass ich dieses Problem nicht hätte, wenn ich “git stash apply” anstelle von “git stash pop” verwende, und wenn ich “git stash save Botschaft” dann wäre das Commit vielleicht einfacher zu finden gewesen.

Update: Mit Nathans Idee wird das kürzer:

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

Benutzer-Avatar
Emragins

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 einer Pipe zu tun, aber das erledigt die Aufgabe.

git fsck --unreachable | grep commit sollte sha1 anzeigen, obwohl die zurückgegebene Liste ziemlich groß sein könnte. git show <sha1> wird zeigen, ob es das gewünschte Commit ist.

git cherry-pick -m 1 <sha1> wird den Commit mit dem aktuellen Zweig zusammenführen.

1330120cookie-checkWie stelle ich einen gelöschten Stash in Git wieder her?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy