Rückgängigmachen von versehentlichem Git Stash Pop

186

Ich habe einige lokale Änderungen gespeichert, bevor ich eine komplizierte Zusammenführung durchgeführt habe, die Zusammenführung durchgeführt und dann dumm vergessen, vor dem Ausführen eine Festschreibung vorzunehmen git stash pop. Der Pop verursachte einige Probleme (schlechte Methodenaufrufe in einer großen Codebasis), die sich als schwer zu finden herausstellen. Ich bin gelaufen git stash show, damit ich zumindest weiß, welche Dateien geändert wurden. Wenn nichts anderes, denke ich, ist dies eine Lektion, um mehr zu begehen.

Meine Frage: Ist es möglich, den Stash Pop rückgängig zu machen, ohne auch die Zusammenführung rückgängig zu machen?

nren
quelle
2
Du sollst es nicht dürfen, git stash popohne dich vorher zu verpflichten. Was haben Sie getan, um das zu erreichen?
Chris Jester-Young
Ich bin mir nicht sicher, ob ich ehrlich bin (das war gestern). Die Fusion wurde nicht von alleine festgelegt, da es Konflikte gab. Danach konnte ich irgendwie Stash Pop laufen lassen.
nren
1
Ich wusste dies nur mit Git Version 1.7.9.msysgit.0. Ich hatte nicht bereitgestellte Dateien und der Stash Pop hat einfach alles zusammengeführt.
PandaWood
Ich konnte git stash popnach dem Staging der Änderungen (die ich jedoch nicht festgeschrieben habe) mit der Version 2.25.0.windows.1 von git
Artem Hevorhian
Wenn Sie Ihre Änderungen indiziert und beim Ausführen stash pop/applyvor dem Festschreiben verloren haben, können Sie sie auslösen git fsck --lost-found. Dieser Befehl durchläuft die baumelnden Blobs (tatsächliche Dateien für diejenigen, die mit der Git-Terminologie nicht vertraut sind), die bereitgestellt, aber nirgendwo festgeschrieben wurden (daher baumeln), und legt sie unter dem Verzeichnis .git / lost-found / ab , wo Sie git showsie sehen können wenn dies die Dateien sind, nach denen Sie suchen.
Artem Hevorhian

Antworten:

69

Versuchen Sie, Wie man einen abgelegten Stash in Git wiederherstellt. um das Versteck zu finden, das du aufgetaucht bist. Ich denke, es gibt immer zwei Commits für einen Stash, da der Index und die Arbeitskopie erhalten bleiben (so oft ist das Index-Commit leer). Dann sehen git showsie den patch -RUnterschied und verwenden ihn , um sie zu entfernen.

Ben Jackson
quelle
6
Wow das hat funktioniert. Ich konnte die Stash-Commits mit git fsck --no-reflog | awk '/dangling commit/ {print $3}'(über den Link) finden und habe das Problem von diesem Diff einfach manuell gefunden. Vielen Dank!
nren
1
das fsck gibt eine riesige liste aus. Es ist mühsam, jeden SHA1 da draußen zu zeigen. Wie machst Du das ?
Meson10
5
@ meson10: Leider werden Stashes in einem Reflog aufbewahrt, was die offensichtliche Möglichkeit wäre (wenn sie ein echter Zweig wären), die Geschichte der Popped Stashes zu betrachten. Lassen Sie mich auch vorschlagen, dass eine Ablehnung + Bitte um Hilfe nicht die beste Strategie ist.
Ben Jackson
2
Ich brauchte ein bisschen Verstümmelung, um es richtig zu machen. Hier ist das Ergebnis meiner Arbeit : git diff -p ${STACH_SHA1}~1 ${STASH_SHA1} | patch -R -p1; Ich habe es git showwie vorgeschlagen versucht , aber die Ausgabe war nicht gut für Patches. auch hatte ich das bietet -p1Option Patch, um das abzustreifen a/..und b/..Element , dass git diffPuts vor den Dateien sonst nicht die Pfade aus der Repository Wurzel lösen würde. VORSCHLAG: Seien Sie vorsichtig und begehen Sie das Chaos in einem separaten Zweig, bevor Sie mit dem Patch spielen.
Basilikode
@BenJackson In Ihrer Antwort bedeutet "immer" beides stash popund stash pushlöst ein Commit aus, das die Änderungen an Index und Arbeitsverzeichnis speichert, oder?
Artem Hevorhian
36

Von git stash --help

Recovering stashes that were cleared/dropped erroneously
   If you mistakenly drop or clear stashes, they cannot be recovered through the normal safety mechanisms. However, you can try the
   following incantation to get a list of stashes that are still in your repository, but not reachable any more:

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

Dies half mir besser als die akzeptierte Antwort mit dem gleichen Szenario.

Kachar
quelle
13
Beachten Sie, dass viele Lösungen, bei denen nach "WIP" gesucht wird, auf den Standard-Stash-Nachrichten basieren. Wenn Sie Ihren Stashes explizite Nachrichten geben, enthalten diese möglicherweise kein WIP.
Ben Jackson
Vielen Dank. Ich habe dem Befehl log die Option --oneline hinzugefügt, um die Lesbarkeit zu verbessern.
Basslo
Dies hilft Ihnen nur, die SHA des Stash-Commits zu finden. Aber wenn in @basilikode Kommentar aus der akzeptierten Antwort integriert (git diff SHA ~ 1 SHA | patch -R), funktioniert es gut. Ich empfehle, zuerst den Pfad --dry-run zu verwenden, um dies zu überprüfen.
Jarek C
2

Wenn Ihre Zusammenführung nicht zu kompliziert wäre, wäre eine andere Option:

  1. Verschieben Sie alle Änderungen einschließlich der Zusammenführungsänderungen mit "git stash" zurück in stash.
  2. Führen Sie die Zusammenführung erneut aus und übernehmen Sie Ihre Änderungen (ohne die Änderungen aus dem abgelegten Stash).
  3. Führen Sie einen "Git Stash Pop" aus, der alle Änderungen aus Ihrer vorherigen Zusammenführung ignorieren sollte, da die Dateien jetzt identisch sind.

Danach bleiben nur noch die Änderungen aus dem Vorrat übrig, den Sie zu früh fallen gelassen haben.

Markus
quelle