Wie kann man einen Stash rückgängig machen?

233

Ich habe einen kleinen Patch in meinem Git-Vorrat gespeichert. Ich habe es mit auf meine Arbeitskopie angewendet git stash apply. Jetzt möchte ich diese Änderungen rückgängig machen, indem ich den Patch rückwärts anwende (ähnlich wie git revertbei dem Stash).

Weiß jemand, wie man das macht?

Klarstellung: Es gibt andere Änderungen in meiner Arbeitskopie. Mein spezieller Fall ist schwer zu beschreiben, aber Sie können sich Debugging oder experimentellen Code vorstellen, der sich im Vorrat befindet. Jetzt ist es in meiner Arbeitskopie mit einigen anderen Änderungen gemischt und ich möchte den Effekt mit und ohne die Änderungen aus dem Vorrat sehen.

Es sieht nicht so aus, als ob Stash dies derzeit unterstützt, aber ein git stash apply --reversewäre eine nette Funktion.

Pat Notz
quelle
1
Können Sie nicht einfach einen umgekehrten Patch erstellen, indem Sie zwischen der aktuellen und der vorherigen Version unterscheiden? Und dann das anwenden?
Ralphtheninja
Gibt es andere Änderungen im Arbeitsbaum als den angewendeten Stash?
Greg Bacon
Dies hier hinzuzufügen
Don Thomas Boyle

Antworten:

188

Laut der git-stash-Manpage wird "Ein Stash als Commit dargestellt, dessen Baum den Status des Arbeitsverzeichnisses aufzeichnet, und sein erstes übergeordnetes HEADElement ist das Commit zum Zeitpunkt der Erstellung des Stashs" und git stash show -pgibt uns die im Versteck als Unterschied zwischen dem Versteckzustand und seinem ursprünglichen Elternteil.

Verwenden Sie git stash show -p | patch --reversewie folgt, um Ihre anderen Änderungen beizubehalten :

$ git init
Initialized empty Git repository in /tmp/repo/.git/

$ echo Hello, world >messages

$ git add messages

$ git commit -am 'Initial commit'
[master (root-commit)]: created 1ff2478: "Initial commit"
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 messages

$ echo Hello again >>messages

$ git stash

$ git status
# On branch master
nothing to commit (working directory clean)

$ git stash apply
# On branch master
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   messages
#
no changes added to commit (use "git add" and/or "git commit -a")

$ echo Howdy all >>messages

$ git diff
diff --git a/messages b/messages
index a5c1966..eade523 100644
--- a/messages
+++ b/messages
@@ -1 +1,3 @@
 Hello, world
+Hello again
+Howdy all

$ git stash show -p | patch --reverse
patching file messages
Hunk #1 succeeded at 1 with fuzz 1.

$ git diff
diff --git a/messages b/messages
index a5c1966..364fc91 100644
--- a/messages
+++ b/messages
@@ -1 +1,2 @@
 Hello, world
+Howdy all

Bearbeiten:

Eine leichte Verbesserung ist die Verwendung git applyanstelle des Patches:

git stash show -p | git apply --reverse

Alternativ können Sie auch git apply -Rals Abkürzung für verwenden git apply --reverse.

Ich fand das in letzter Zeit sehr praktisch ...

Greg Bacon
quelle
2
Super, danke. Scheint so, als wäre dies eine nette Funktion für Stash.
Pat Notz
5
Ja, git apply -Rist eine Verbesserung, zumindest für mich auf meiner Windows-Box mit Git Bash, da ich patch --reverseProbleme hatte, die zu patchende Datei zu finden (kein wirklicher Hinweis, warum die Alternative funktioniert hat). +1 und gute Erklärung
hakre
wäre es nicht besser, hinzuzufügen , --indexwie diese git stash show -p | git apply --reverse --index. Da Sie die zurückgesetzten Änderungen nicht mehr im Index hinzufügen müssen.
theUnknown777
3
@ Greg Bacon, hey, ich habe versucht, das von Ihnen beschriebene Skript durchzugehen, aber der Patch ist fehlgeschlagen, als ich git stash show -p | git apply -R -vmit der folgenden Meldung ausgeführt habe : Checking patch messages... error: while searching for: Hello, world Hello again error: patch failed: messages:1. Wissen Sie, was falsch sein könnte?
Max Koretskyi
5
Ich erhalte die Fehlermeldung: Patch fehlgeschlagen: /src/filename.java:46 Fehler: Der Patch src /
Tim Boland
83

git stash[save]Nimmt Ihren Arbeitsverzeichnisstatus und Ihren Indexstatus und verwahrt sie, wodurch Index und Arbeitsbereich auf HEADVersion gesetzt werden.

git stash applybringt diese Änderungen zurück, git reset --hardwürde sie also wieder entfernen.

git stash popBringt diese Änderungen zurück und entfernt die obersten versteckten Änderungen. git stash [save]In diesem Fall würde der vorherige Status (Pre-Pop) wiederhergestellt.

Jakub Narębski
quelle
82
git checkout -f

entfernt alle nicht festgeschriebenen Änderungen.

Salman
quelle
4
danke, du hilfst mir von inszenierten Veränderungen, die nicht unangebracht waren.
Fa.Shapouri
1
Dies war viel einfacher
Mark A
Das war großartig!
Kiran Sk
22

Die V1-Git-Manpage enthielt einen Verweis zum Aufheben der Anwendung eines Stashs. Der Auszug ist unten.

Die neuere V2- Git-Manpage enthält keinen Hinweis darauf, dass ein Stash nicht angewendet wird, aber das Folgende funktioniert immer noch gut

Aufheben der Anwendung eines Stashs In einigen Anwendungsszenarien möchten Sie möglicherweise versteckte Änderungen anwenden, einige Arbeiten ausführen und dann die ursprünglich aus dem Stash stammenden Änderungen aufheben. Git bietet keinen solchen Befehl zum Aufheben der Anwendung des Stashs, aber es ist möglich, den Effekt zu erzielen, indem Sie einfach den mit einem Stash verknüpften Patch abrufen und ihn umgekehrt anwenden:

$ git stash show -p stash@{0} | git apply -R

Wenn Sie keinen Stash angeben, geht Git von dem neuesten Stash aus:

$ git stash show -p | git apply -R

Möglicherweise möchten Sie einen Alias ​​erstellen und Ihrem Git effektiv einen Stash-Unapply-Befehl hinzufügen. Beispielsweise:

$ git config --global alias.stash-unapply '!git stash show -p | git apply -R'
$ git stash apply
$ #... work work work
$ git stash-unapply
Choco Smith
quelle
1
Aus welchem ​​Grund auch immer, dieser hilfreiche Abschnitt, den Sie mit " Nicht -Anwenden eines Stashs" verknüpft haben, wurde aus der 2. Version entfernt. Die aktuellste Version ist 2.1.146, 2019-04-15- dieses Buches. V2- Git Tools - Stashing and Cleaning . Könnte daran liegen, dass die Autoren glauben, dass es einen besseren Weg gibt, den ich nicht zu finden scheine.
Nad Alaba
@ NadAlaba danke für das Heads-up, habe die Antwort aktualisiert, um den Unterschied zwischen v1 und v2 zu notieren ... seltsam, die Git-Autoren haben den Abschnitt über das Aufheben der Anwendung eines Stashs entfernt
Choco Smith
13

Dies ist längst überfällig, aber wenn ich das Problem richtig interpretiere, habe ich eine einfache Lösung gefunden. Beachten Sie, dass dies eine Erklärung in meiner eigenen Terminologie ist:

git stash [save] speichert aktuelle Änderungen und versetzt Ihren aktuellen Zweig in den "sauberen Zustand"

git stash list gibt so etwas wie: stash@{0}: On develop: saved testing-stuff

git apply stash@{0}stellt den aktuellen Zweig wie zuvor ein stash [save]

git checkout .Setzt den aktuellen Zweig wie folgt stash [save]

Der im Stash gespeicherte Code geht nicht verloren, er kann von git apply stash@{0}wieder gefunden werden .

Wie auch immer, das hat bei mir funktioniert!

Schlanker Sim
quelle
Nur um sicher zu gehen, habe ich mich zuerst beworben git stash apply --reverseund bin dann einfach zurückgegangen, git stash apply stash@{x}wie Sie es erwähnt haben. Arbeitete ohne Probleme.
Carlos Garcia
3

Wie kann man einen Stash rückgängig machen?

Abgesehen von dem, was andere erwähnt haben, ist der einfachste Weg, zuerst zu tun

git reset HEAD

und dann alle lokalen Änderungen auschecken

git checkout . 
Achal
quelle
Dies ist bei weitem der einfachste Weg, solange Sie absolut keine lokale Arbeit haben, die Sie speichern möchten. Wenn Sie den falschen Stash auf einen Zweig angewendet haben oder Zusammenführungskonflikte treffen, die Sie nicht lösen möchten, können Sie dies schnell und einfach rückgängig machen, indem Sie Ihren Arbeitssatz vollständig auf das neueste Commit Ihres Zweigs zurücksetzen.
Shadoninja
2

Zusätzlich zur Antwort von @Greg Bacon, falls Binärdateien zum Index hinzugefügt wurden und Teil des Stashs mit waren

git stash show -p | git apply --reverse

Kann dazu führen, dass

error: cannot apply binary patch to '<YOUR_NEW_FILE>' without full index line
error: <YOUR_NEW_FILE>: patch does not apply

Das Hinzufügen --binarybehebt das Problem, hat aber leider noch nicht herausgefunden, warum.

 git stash show -p --binary | git apply --reverse
MHosafy
quelle
0

Dies ist zusätzlich zu den obigen Antworten, fügt jedoch die Suche nach dem Git-Stash basierend auf der Nachricht hinzu, da sich die Stash-Nummer ändern kann, wenn neue Stashes gespeichert werden. Ich habe ein paar Bash-Funktionen geschrieben:

apply(){
  if [ "$1" ]; then
    git stash apply `git stash list | grep -oPm1 "(.*)(?=:.*:.*$1.*)"`
  fi
}
remove(){
  if [ "$1" ]; then
    git stash show -p `git stash list | grep -oPm1 "(.*)(?=:.*:.*$1.*)"` | git apply -R
    git status
  fi
}
  1. Versteck mit Namen erstellen (Nachricht) $ git stash save "my stash"
  2. Zu benennen $ apply "my stash"
  3. So benannte Stash entfernen $ remove "my stash"
lebenswichtig
quelle
0

Sie können dem Bild folgen, das ich freigegeben habe, um es zu entfernen, wenn Sie versehentlich auf das Speichern getippt haben.

Amanpreet Singh
quelle