Frage

Ich benutze es 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 zwischengespeichert und gelöscht hatte, und dann habe ich weitere Änderungen an meinem Arbeitsbaum vorgenommen.Ich würde gerne noch einmal zurückgehen und die gespeicherten Änderungen von gestern überprüfen, aber git stash pop scheint alle Verweise auf das zugehörige Commit zu entfernen.

Ich weiß das, wenn ich es 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 der 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?

Beachten Sie, dass dies für mich heute nicht kritisch ist, da ich über tägliche Backups verfüge und zum gestrigen Arbeitsbaum zurückkehren kann, um meine Änderungen abzurufen.Ich frage, weil es einen einfacheren Weg geben muss!

War es hilfreich?

Lösung

Wenn Sie die Hash-Wert des Stash wissen verpflichten Sie fallen gelassen, können Sie es als Stash anwenden können:

git stash apply $stash_hash

Alternativ können Sie einen eigenen Zweig für sie mit

erstellen
git branch recovered $stash_hash

Danach können Sie tun, was Sie mit all den üblichen Werkzeugen wollen. Wenn Sie fertig sind, nur den Zweig wegblasen.

Suche nach der Hash

Wenn Sie gerade erst knallte es und das Terminal ist noch offen, werden Sie haben immer noch den von git stash pop auf dem Bildschirm gedruckten Hashwert (danke, Dolda).

Sie können aber finden es dies mit für Linux, Unix oder Git Bash für Windows:

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

... oder mit Powershell für Windows:

git fsck --no-reflog | select-string 'dangling commit' | foreach { $bits = $_ -split ' '; echo $bits[2];}

Dies zeigt Ihnen alle Commits an den Spitzen der commit grafische Darstellung, die nicht mehr von jedem Zweig oder ein Tag referenziert werden - jeder verloren begehen, einschließlich jedes Versteck begehen Sie jemals erstellt haben, wird in diesem Diagramm irgendwo sein <. / p>

Der einfachste Weg, um das Versteck zu finden commit Sie wollen, ist wahrscheinlich, dass die Liste zu übergeben gitk:

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

... oder finden Sie unter die Antwort von emragins bei Verwendung von Powershell für Windows.

Dies wird ein Repository Browser starten zeigen Sie begehen jedes einzelne im Repository immer , und zwar unabhängig davon, ob sie erreichbar ist oder nicht.

Sie können gitk ersetzen es mit so etwas wie git log --graph --oneline --decorate wenn Sie eine schöne Grafik auf der Konsole über eine separate GUI-Anwendung bevorzugen.

Stash Commits zu erkennen, suchen Sie nach Nachrichten dieser Form zu begehen:

WIP auf somebranch : commithash Einige alte Commit-Nachricht

Hinweis . Die Nachricht nur in dieser Form sein begehen wird (beginnend mit "WIP on"), wenn Sie haben eine Nachricht nicht angeben, wenn Sie git stash tun

Andere Tipps

Wenn Sie nicht das Terminal schließen, schauen Sie am Ausgang von git stash pop und Sie werden die Objekt-ID des sank Stash haben. Es sieht normalerweise wie folgt aus:

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

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

Um dieses Versteck zurück, nur git branch tmp 2cae03e laufen, und Sie werden es als Zweig erhalten. So konvertiert dies zu einem Versteck, führen Sie:

git stash apply tmp
git stash

Nachdem sie als auch eine Niederlassung ermöglicht es, frei zu manipulieren; beispielsweise herauspicken es oder sie fusionieren.

Ich wollte nur diese zusätzlich zu der akzeptierten Lösung erwähnen. Es war nicht sofort offensichtlich für mich das erste Mal, dass ich diese Methode versuchte (vielleicht sollte es gewesen sein), aber das Versteck aus dem Hash-Wert anzuwenden, verwenden Sie einfach „Git Stash anwenden“:

$ git stash apply ad38abbf76e26c803b27a6079348192d32f52219

Als ich git neu war, war das für mich nicht klar, und ich habe versucht, verschiedene Kombinationen von "git show", "git apply", "Patch", etc.

Um die Liste des stashes zu erhalten, die nach wie vor in Ihrem Repository ist, aber nicht mehr erreichbar:

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

Wenn Sie einen Titel zu Ihrem Versteck geben, ersetzen „WIP“ in -grep=WIP am Ende des Befehls mit einem Teil Ihrer Nachricht, z.B. -grep=Tesselation.

Der Befehl für „WIP“ wird greppen da die Standard-Nachricht für einen Stash begehen ist in Form WIP on mybranch: [previous-commit-hash] Message of the previous commit.

Ich konstruierte nur einen Befehl, der mir geholfen, meine verloren Stash begehen 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

Diese listet alle Objekte in der .git / Objekte Baum lokalisiert diejenigen, die vom Typ sind begehen, zeigt dann eine Zusammenfassung jedes einzelnen. Von diesem Punkt war es nur eine Frage der Suche durch die Commits einen entsprechenden „WIP auf der Arbeit: 6a9bb2“ zu finden ( „Arbeit“ mein Zweig ist, 619bb2 eine kürzliches ist Festschreibung)

.

Ich stelle fest, dass, wenn ich „Git Stash anwenden“ anstelle von „git stash pop“ verwenden würde ich dieses Problem nicht haben, und wenn ich „save git stash Nachricht “, dann könnte die commit einfacher gewesen, zu finden.

Update: Mit Nathans Idee, diese kürzer wird:

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

git fsck --unreachable | grep commit sollte den SHA1 zeigen, obwohl die Liste es gibt möglicherweise recht groß. git show <sha1> wird zeigen, ob es die begehen Sie wollen.

git cherry-pick -m 1 <sha1> fusionieren die auf den aktuellen Zweig zu begehen.

Wenn Sie einen verlorenen Stash wiederherstellen möchten, müssen Sie zuerst den Hash Ihres verlorenen Stashs finden.

Wie Aristoteles Pagaltzis vorschlug, a git fsck sollte dir helfen.

Persönlich benutze ich meine log-all Alias, der mir jedes Commit (wiederherstellbare Commits) zeigt, 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)

Sie können eine noch schnellere Suche durchführen, wenn Sie nur nach „WIP on“-Nachrichten suchen.

Sobald Sie Ihren sha1 kennen, ändern Sie einfach Ihr Stash-Reflog, um den alten Stash hinzuzufügen:

git update-ref refs/stash ed6721d

Sie möchten wahrscheinlich eine zugehörige Nachricht haben, z -m

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

Und Sie möchten dies sogar als Alias ​​verwenden:

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

Windows Powershell-äquivalent mit gitk:

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

Es ist wahrscheinlich ein effizienter Weg, dies in einem Rohr zu tun, aber das macht den Job.

Ich mochte Aristoteles Ansatz, aber nicht wie GITK mit ... wie ich mit GIT von der Kommandozeile verwendet werde.

Stattdessen nahm ich die baumelnden verpflichtet und Ausgang, den Code zu einer DIFF-Datei zur Überprüfung in meinem Code-Editor.

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

Jetzt können Sie die resultierende diff / txt-Datei laden (seine in Ihrem Home-Ordner) in die txt-Editor und sehen den eigentlichen Code und die daraus resultierenden SHA.

Dann benutzen Sie einfach

git stash apply ad38abbf76e26c803b27a6079348192d32f52219

In OSX mit git v2.6.4, ich git stash Tropfen nur zufällig laufen, dann fand ich es von unten beschriebenen Schritte gehen Trog

Wenn Sie Namen des Stash wissen dann verwenden:

$ git fsck --unreachable | grep commit | cut -c 20- | xargs git show | grep -B 6 -A 2 <name of the stash>

Sie sonst ID aus dem Ergebnis finden, indem Sie manuell mit:

$ git fsck --unreachable | grep commit | cut -c 20- | xargs git show

Wenn Sie dann die Commit-ID finden einfach auf die Git Stash anwenden {commit-id}

Hope dies jemand hilft schnell

Warum fragen Leute diese Frage? Weil sie noch nicht kennen oder die reflog verstehen.

Die meisten Antworten auf diese Frage geben lange Befehle mit Optionen wird fast niemand erinnern. So können die Leute kommen in diese Frage kopieren und einfügen, was sie denken, sie brauchen und sie vergessen, fast unmittelbar nach.

würde ich jeden mit dieser Frage berät nur die reflog (git reflog) zu überprüfen, nicht viel mehr als das. Sobald Sie diese Liste aller sehen verpflichtet es hundert Möglichkeiten, um herauszufinden, was begehen Sie suchen und es herauspicken oder einen Zweig von ihm erstellen. In dem Prozess haben Sie über die reflog und nützliche Optionen, um verschiedene Grund git Befehle gelernt.

Sie können alle nicht erreichbaren Commits Liste mit diesem Befehl im Terminal zu schreiben -

git fsck --unreachable

Überprüfen Sie nicht erreichbar Hash begehen -

git show hash

Schließlich gilt, wenn Sie die verstaute Artikel finden -

git stash apply hash

Ich möchte eine andere gute Möglichkeit, um die akzeptierte Lösung hinzuzufügen, durch alle Änderungen zu gehen, wenn Sie entweder nicht verfügbar oder gitk kein X für die Ausgabe haben.

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

for h in `cat tmp_commits`; do git show $h | less; done

Sie erhalten dann alle Differentiale für die Hash-Werte nacheinander angezeigt. Drücken Sie 'q', um zum nächsten diff zu erhalten.

Die akzeptierte Antwort von Aristoteles wird alle erreichbaren Commits zeigen, einschließlich nicht-Stash-like Commits. Um herauszufiltern das Rauschen:

git fsck --no-reflog | \
awk '/dangling commit/ {print $3}' | \
xargs git log --no-walk --format="%H" \
  --grep="WIP on" --min-parents=3 --max-parents=3

Dies wird nur verpflichtet ist, die genau 3 Elternteil verpflichtet (die ein Versteck haben wird), und deren Meldung enthält „WIP auf“.

Beachten Sie, dass, wenn Sie Ihren Stash mit einer Nachricht (z git stash save "My newly created stash") gespeichert, das die Standardeinstellung überschreiben wird „WIP auf ...“ angezeigt.

Sie können mehr Informationen anzeigen zu jedem Commit, z.B. Anzeige der Commit-Nachricht, oder gibt es an git stash show:

git fsck --no-reflog | \
awk '/dangling commit/ {print $3}' | \
xargs git log --no-walk --format="%H" \
  --grep="WIP on" --min-parents=3 --max-parents=3 | \
xargs -n1 -I '{}' bash -c "\
  git log -1 --format=medium --color=always '{}'; echo; \
  git stash show --color=always '{}'; echo; echo" | \
less -R

Ich konnte keine der Antworten bekommen unter Windows in einem einfachen Befehlsfenster (Windows 7 in meinem Fall) zu arbeiten. awk, grep und Select-string wurden nicht als Befehle erkannt. Also habe ich versucht, einen anderen Ansatz:

  • erster Lauf: git fsck --unreachable | findstr "commit"
  • Kopieren Sie die Ausgabe auf Notizblock
  • finden ersetzen "nicht erreichbar commit" mit start cmd /k git show

wird wie folgt aussehen:

start cmd /k git show 8506d235f935b92df65d58e7d75e9441220537a4 start cmd /k git show 44078733e1b36962571019126243782421fcd8ae start cmd /k git show ec09069ec893db4ec1901f94eefc8dc606b1dbf1 start cmd /k git show d00aab9198e8b81d052d90720165e48b287c302e

  • Speichern als BAT-Datei und führen Sie es
  • das Skript eine Reihe von Befehlsfenster öffnen, zeigt jedem Commit
  • , wenn Sie die eine Sie suchen gefunden, laufen: git stash apply (your hash)

vielleicht nicht die beste Lösung sein, aber für mich gearbeitet

Was ich hergekommen suchen ist, wie eigentlich das Versteck zurück zu erhalten, und zwar unabhängig von dem, was ich habe ausgecheckt. Insbesondere habe ich etwas versteckt, dann überprüft heraus eine ältere Version, poped es dann, aber das Versteck war ein No-op zu diesem früheren Zeitpunkt, so dass der Vorrat verschwunden; Ich kann nicht nur git stash tun, um es auf dem Stapel zurückschieben. Dieser arbeitete für mich:

$ git checkout somethingOld
$ git stash pop
...
nothing added to commit but untracked files present (use "git add" to track)
Dropped refs/stash@{0} (27f6bd8ba3c4a34f134e12fe69bf69c192f71179)
$ git checkout 27f6bd8ba3c
$ git reset HEAD^    # Make the working tree differ from the parent.
$ git stash # Put the stash back in the stack.
Saved working directory and index state WIP on (no branch): c2be516 Some message.
HEAD is now at c2be516 Some message.
$ git checkout somethingOld # Now we are back where we were.

Im Nachhinein sollte ich habe mit git stash apply git stash pop nicht. Ich war dabei ein bisect und hatte einen kleinen Patch, den ich bei jedem Schritt bisect anwenden wollte. Nun ist diese ich tue:

$ git reset --hard; git bisect good; git stash apply
$ # Run tests
$ git reset --hard; git bisect bad; git stash apply
etc.

Recovered es mithilfe folgende Schritte:

  1. Geben Sie den gelöschten Stash Hash-Code:

    gitk --alle $ (git fsck --no-reflog | awk '/ baumelnden begehen / {print $ 3}')

  2. Cherry Wählen Sie die Stash:

    git cherry-pick -m 1 $ stash_hash_code

  3. Konflikte lösen, wenn jeder mit:

    git mergetool

Zusätzlich können Probleme mit werden mit Commit-Nachricht, wenn Sie gerrit verwenden. Bitte Stash Ihre Änderungen vor folgenden nächste Alternativen:

  1. Verwenden Sie Reset schwer zu vorherigen begehen und dann diese Änderung verpflichten.
  2. Sie können auch die Änderung bunkern, rebase und verpflichten.

Ich habe versehentlich das Versteck in GitUP App entfernt. Drücken Sie Strg + Z Nur um es rückgängig gemacht.

Vielleicht hilft es jemand;)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top