Git-Stash: "Kann nicht auf einen schmutzigen Arbeitsbaum angewendet werden, bitte stellen Sie Ihre Änderungen bereit"

133

Ich versuche, Änderungen anzuwenden, mit denen ich zuvor verwahrt habe, git stash popund erhalte die folgende Nachricht:

Cannot apply to a dirty working tree, please stage your changes

Irgendwelche Vorschläge, wie man damit umgeht?

Avernet
quelle

Antworten:

196

Wenn ich versteckte Änderungen auf eine schmutzige Arbeitskopie anwenden muss, z. B. mehr als einen Änderungssatz aus dem Stash entfernen möchte, verwende ich Folgendes:

$ git stash show -p | git apply -3 && git stash drop

Grundsätzlich ist es

  1. erstellt einen Patch
  2. leitet das an den Befehl apply weiter
  3. Wenn es Konflikte gibt, müssen diese durch 3-Wege-Zusammenführung gelöst werden
  4. Wenn das Anwenden (oder Zusammenführen) erfolgreich war, wird das gerade angewendete Stash-Element gelöscht ...

Ich frage mich, warum es keine -f(Kraft-) Option gibt, für git stash popdie sich genau wie der Einzeiler oben verhalten sollte.

In der Zwischenzeit möchten Sie diesen Einzeiler möglicherweise als Git-Alias ​​hinzufügen:

$ git config --global --replace-all alias.unstash \
   '!git stash show -p | git apply -3 && git stash drop'
$ git unstash

Vielen Dank an @SamHasler für den Hinweis auf den -3Parameter, mit dem Konflikte direkt über 3-Wege-Zusammenführung gelöst werden können.

muhqu
quelle
Ist git stash show -p | git applyanders als git stash apply?
Faktor Mystic
1
Jo Factor git stash applyübernimmt die versteckten Änderungen nicht, wenn Sie eine schmutzige Arbeitskopie haben. Sie können also sehen, git stash show -p | git applywie eine Art erzwungenes Versteck angewendet wird .
Muhqu
1
hilft nicht aber hilft: git setze HEAD zurück und lösche danach die Änderungen.
Roger Alien
4
Ich erhalte "Fehler: Patch fehlgeschlagen ... Patch gilt nicht" für eine der Dateien. Ich wünschte, es hätte einen Zusammenführungskonflikt gegeben.
Aleksandr Dubinsky
1
Diese Lösung hat bei mir nicht funktioniert, sie ist bei error: <file> does not match indexjeder geänderten Datei fehlgeschlagen . Eine andere Lösung funktionierte jedoch.
Silvenon
57

Ich mache es so:

git add -A
git stash apply

und dann (optional):

git reset
Sergii Mostovyi
quelle
2
+1! Dies ist einfacher als die anderen Lösungen, bei denen Patches generiert oder Commits geändert werden, und Ihre lokalen Änderungen werden sicher von den angewendeten Stash-Änderungen isoliert, bis Sie sicher sind, dass die Änderungen ordnungsgemäß zusammengeführt wurden.
Peterflynn
Ich erhalte die Fehlermeldung "... existiert bereits, keine Kasse ... Unverfolgbare Dateien konnten nicht aus dem Stash wiederhergestellt werden"
Aleksandr Dubinsky
2
Ich habe verwendet git add -u, was so ist, -Aaußer dass es keine nicht verfolgten Dateien hinzufügt.
Brad Cupit
9

Sie können dies tun, ohne Ihre aktuellen Änderungen speichern zu müssen, indem Sie den gewünschten Speicher als Patch-Datei exportieren und manuell anwenden.

Angenommen, Sie möchten stash @ {0} auf einen schmutzigen Baum anwenden:

  1. Exportieren Sie stash @ {0} als Patch:

    git stash show -p stash @ {0}> Stash0.patch

  2. Übernehmen Sie die Änderungen manuell:

    Git anwenden Stash0.patch

Wenn der zweite Schritt fehlschlägt, müssen Sie die Datei Stash0.patch bearbeiten, um Fehler zu beheben, und dann erneut versuchen, git apply anzuwenden.

Ishan
quelle
Dies ist praktisch und praktikabel für den Fall, dass ich ein Verzeichnis umgestaltet habe (es entfernt und einen Symlink mit seinem Namen erstellt habe). Git konnte nicht sagen, was meine Änderungen an der Arbeitskopie waren.
Yclian
1
Das hat super geklappt. Ich konnte keinen Stash anwenden, obwohl ich mir ziemlich sicher bin, dass mein Arbeitsbaum sauber ist.
Shiki
Ja, ich musste Zeilen über eine Binärdatei entfernen.
Dorian
8

Bereinigen Sie entweder Ihr Arbeitsverzeichnis mit git reset, übernehmen Sie die Änderungen oder versuchen Sie Folgendes, wenn Sie die aktuellen Änderungen speichern möchten:

$ git stash save "Beschreibung der aktuellen Änderungen"
$ git stash pop stash @ {1}

Dadurch werden die aktuellen Änderungen gespeichert und dann der zweite Speicher aus dem Stapel gestapelt.

William Pursell
quelle
5
Aber dieser Typ möchte, dass die beiden Verstecke angewendet werden!
Elazar Leibovich
@ Elzar Sie lesen in die Frage. Das OP möchte lediglich einen vorherigen Vorrat anwenden. Wenn Sie richtig sind, dass die aktuellen Änderungen beibehalten werden sollen, kann die Lösung wiederholt werden: Pop, Commit, Repeat.
William Pursell
Ich denke, er möchte, dass beide nicht verpflichtet sind. Andererseits kann er sie zweimal festschreiben und zu einem einzigen Festschreiben zusammenfassen.
Elazar Leibovich
Ich erhalte die Fehlermeldung "... existiert bereits, keine Kasse ... Unverfolgbare Dateien konnten nicht aus dem Stash wiederhergestellt werden"
Aleksandr Dubinsky
6

Die Lösung von Mathias kommt definitiv einer Git-Stash-Pop-Force am nächsten (und wirklich, komm schon, Git-Entwickler, lass uns diese Option schon bekommen!)

Wenn Sie jedoch dasselbe nur mit Git-Befehlen tun möchten, können Sie:

  1. git commit -a -m "Fixme"
  2. Git Stash Pop
  3. git commit -a --amend
  4. Git Reset HEAD ~

Mit anderen Worten, machen Sie ein Commit (das wir niemals pushen werden) Ihrer aktuellen Änderungen. Jetzt, da Ihr Arbeitsbereich sauber ist, legen Sie Ihren Vorrat ab. Übernehmen Sie jetzt die Stash-Änderungen als Änderung Ihres vorherigen Commits. Nachdem Sie dies getan haben, haben Sie jetzt beide Änderungssätze in einem einzigen Commit zusammengefasst ("Fixme"). Setzen Sie einfach Ihre Kaufabwicklung auf "Eins vor diesem Festschreiben" zurück (--soft NOT --hard, damit tatsächlich nichts verloren geht), und jetzt haben Sie beide Änderungssätze, die nicht festgeschrieben sind.

** BEARBEITEN * *

Mir ist gerade klar geworden, dass es sogar noch einfacher ist. Sie können Schritt 3 vollständig überspringen, also ...

  1. git commit -a -m "Fixme"
  2. Git Stash Pop
  3. Git Reset HEAD ~

(Übernehmen Sie die aktuellen Änderungen, entfernen Sie die gespeicherten Änderungen und setzen Sie das erste Festschreiben zurück, um beide Änderungssätze in einem nicht festgeschriebenen Zustand zu kombinieren.)

Maschinenhost
quelle
4

Keine dieser Antworten funktioniert tatsächlich, wenn Sie sich in dieser Situation befinden, wie ich es heute getan habe. Egal wie viele git reset --hardich gemacht habe, es hat mich nirgendwohin gebracht. Meine Antwort (keineswegs offiziell) war:

  1. Finden Sie die Hash-Verwendung des Stash heraus git reflog --all
  2. Führen Sie diesen Hash mit dem Zweig zusammen, an dem Sie interessiert sind
Dan Rosenstark
quelle
1
Vielen Dank Yar. Ich war frustriert darüber, wie sich Git gerade auf meinem lokalen Repo seltsam verhalten hat, das gleiche Problem, das Sie beschrieben haben.
Yclian
4

Ich fand auch, dass die Lösung von Mathias Leppich großartig funktioniert, und fügte meiner globalen .gitconfig einen Alias ​​dafür hinzu

[alias]
        apply-stash-to-dirty-working-tree = !git stash show -p | git apply && git stash drop

Jetzt kann ich einfach tippen

git apply-stash-to-dirty-working-tree

Das funktioniert gut für mich.

(Ihr Kilometerstand kann bei diesem langen Aliasnamen variieren. Aber ich mag eine Portion Ausführlichkeit, wenn es um die Vervollständigung von Bashs geht.)

mat
quelle
3

Sie können einen Versteck auf einen "schmutzigen" Baum anwenden, indem git addSie alle vorgenommenen Änderungen vornehmen und so den Baum bereinigen. Dann können Sie git stash popdie versteckten Änderungen problemlos anwenden.

Chris Vandevelde
quelle
2

Sie haben Dateien, die geändert, aber nicht festgeschrieben wurden. Entweder:

git reset --hard HEAD (to bring everything back to HEAD)

oder, wenn Sie Ihre Änderungen speichern möchten:

git checkout -b new_branch
git add ...
git commit
git checkout -b old_branch
git stash pop
brool
quelle
1
@ MikeCooper - Ich denke, er wollte nur hinzufügen, was Sie hinzufügen möchten, bevor Sie sich verpflichten.
sscirrus
0

Ich hatte das gleiche Problem, aber Git hatte keine geänderten Dateien. Es stellte sich heraus, dass ich eine index.lock-Datei hatte, die herumlag. Das Löschen löste das Problem.

verpackt
quelle
0

Ich konnte die meisten davon nicht zum Laufen bringen; Aus irgendeinem Grund glaubt es immer, dass ich lokale Änderungen an einer Datei habe. Ich kann keinen Stash anwenden, Patches werden nicht angewendet checkoutund reset --hardschlagen fehl. Was schließlich funktionierte, war, den Stash als Zweig mit zu speichern git stash branch tempbranchnameund dann eine normale Zweigzusammenführung durchzuführen: git checkout masterund git merge tempbranchname. Von http://git-scm.com/book/en/Git-Tools-Stashing :

Wenn Sie die versteckten Änderungen auf einfachere Weise erneut testen möchten, können Sie den Git-Stash-Zweig ausführen, der einen neuen Zweig für Sie erstellt, das Commit überprüft, bei dem Sie Ihre Arbeit gespeichert haben, Ihre Arbeit dort erneut anwendet und dann den Löschvorgang löscht Verstecken, wenn es erfolgreich angewendet wird

rwilson04
quelle