Wie kann ich nur bestimmte Dateien entstauen?

386

Ich habe meine Änderungen verstaut. Jetzt möchte ich nur einige Dateien aus dem Stash entfernen. Wie kann ich das machen?

Morpheus
quelle
4
Ich denke, Sie müssen den gesamten Vorrat anwenden, aber dann können Sie ihn selektiv wieder aufbewahren.
Richard
4
@AbdouTahiri Was ist los mit dem Versteck?
Alex
32
@AbdouTahiri Uhhhh .. Git Stash ist eine legitime Funktion und äußerst nützlich. Ich benutze es täglich. Angenommen, ein Mitarbeiter muss etwas überprüfen, aber ich bin mitten in einem komplexen Änderungssatz. Ich werde keinen Stapel defekten Codes festschreiben, nur damit ich die Zweige wechseln kann. Ich werde verstauen, Zweige wechseln, überprüfen, zurückschalten, entstauen. Möchten Sie näher erläutern, wer oder warum Git Stash angeblich "nicht empfohlen" wird? Nur weil deine Git-Stash-Geschichte durcheinander und schwer zu lesen ist, heißt das nicht, dass es jeder andere ist. Ein chaotisches Git-Stash-Set ist nur ein schlechter Workflow, kein Fehler von Git.
Dudewad
6
@alex Nichts. Mit Git Stash ist nichts falsch. Benutze es weiter.
Dudewad

Antworten:

461

Wie unten erwähnt und unter " Wie würde ich eine einzelne Datei (oder Änderungen an einer Datei) aus einem Git-Stash extrahieren? " Ausführlich beschrieben , können Sie die Verwendung git checkoutoder git showdas Wiederherstellen einer bestimmten Datei anwenden .

git checkout stash@{0} -- <filename>

Das wird überschrieben filename : Stellen Sie sicher, dass Sie keine lokalen Änderungen vorgenommen haben, oder Sie möchten stattdessen die versteckte Datei zusammenführen .

(Wie kommentiert von Jaime M. , für bestimmte Shell wie tcsh , wo Sie brauchen , um die Sonderzeichen zu entkommen, würde die Syntax sein: git checkout 'stash@{0}' -- <filename>)

oder um es unter einem anderen Dateinamen zu speichern:

git show stash@{0}:<full filename>  >  <newfile>

(Beachten Sie, dass hier der <full filename>vollständige Pfadname einer Datei relativ zum obersten Verzeichnis eines Projekts angegeben ist (denken Sie: relativ zu stash@{0})).

yucer schlägt in den Kommentaren vor :

Wenn Sie manuell auswählen möchten, welche Änderungen Sie aus dieser Datei übernehmen möchten:

git difftool stash@{0}..HEAD -- <filename>

Vivek fügt in den Kommentaren hinzu :

Sieht so aus, als ob " git checkout stash@{0} -- <filename>" die Version der Datei zum Zeitpunkt der Ausführung des Stashs wiederherstellt - es werden NICHT (nur) die versteckten Änderungen für diese Datei angewendet.
Um Letzteres zu tun:

git diff stash@{0}^1 stash@{0} -- <filename> | git apply

(Wie von Peterflynn kommentiert , müssen Sie in einigen Fällen möglicherweise einen ( ) führenden Schrägstrich aus herkömmlichen Diff-Pfaden entfernen. )| git apply -p1p1


Wie kommentiert: "unstash" ( git stash pop), dann:

  • Fügen Sie dem Index hinzu, was Sie behalten möchten ( git add)
  • Verstecke den Rest: git stash --keep-index

Der letzte Punkt ist, was es Ihnen ermöglicht, einige Dateien zu behalten, während andere gespeichert werden.
Es wird in " So verstauen Sie nur eine Datei aus mehreren Dateien, die sich geändert haben " veranschaulicht .

VonC
quelle
5
Dies funktioniert nicht, wenn dies git stash popaufgrund von Dateikonflikten nicht möglich ist. Die Antwort von Balamurugan A hat in diesem Fall den Trick für mich getan.
Andrey
1
Wenn Sie manuell auswählen möchten, welche Änderungen Sie aus dieser Datei übernehmen möchten, können Sie git difftool stash @ {0} verwenden. HEAD - <Dateiname>
yucer
5
Es sieht so aus, als würde "git checkout stash @ {0} - <Dateiname>" die Version der Datei zum Zeitpunkt der Ausführung des Stashs wiederherstellen - es werden NICHT (nur) die versteckten Änderungen für diese Datei angewendet. Um letzteres zu tun: "git diff stash @ {0} ^ 1 stash @ {0} - <Dateiname> | git apply"
Vivek
1
@ JaimeM. Vielen Dank. Ich habe Ihren Kommentar zur besseren Sichtbarkeit in die Antwort aufgenommen.
VonC
1
Unter der Annahme, dass dies unstashbedeutet pop, wie es mir wahrscheinlich in den meisten Fällen der Fall ist, beantwortet dies die Frage nur teilweise. Wie entfernen Sie dann die selektiv angewendeten Teile aus dem Vorrat, um spätere Konflikte und / oder Verwirrung beim Löschen der verbleibenden Änderungen zu vermeiden?
DylanYoung
115
git checkout stash@{N} <File(s)/Folder(s) path> 

Z.B. Um nur die Datei ./test.c und den Ordner ./include aus dem letzten Speicher wiederherzustellen,

git checkout stash@{0} ./test.c ./include
Balamurugan A.
quelle
12
Das ist die richtige Antwort! Einzeiliger Befehl, um nur versteckte Änderungen aus bestimmten Dateien anzuwenden, funktioniert wie ein Zauber!
4 Ebenen
1
Um (nur) die versteckten Änderungen für die Datei anzuwenden: "git diff stash @ {N} ^ 1 stash @ {N} - <Dateiname> | git apply"
Vivek
Das funktioniert auch bei mir. Checken Sie einfach selektiv die Dateien aus, die für die Verwendung aus dem Stash benötigt werden, und Sie sind fertig. Ich steckte darin fest und hatte -abeim Erstellen des Stashs eine Flagge verwendet .
Rajeev Ranjan
1
@ 4levels Ich denke, "versteckte Änderungen anwenden" ist nicht das, was passiert, oder? Ich denke, "überschreibe alles, was du mit der Kopie aus dem Vorrat hast" ist das, was passiert.
5.
35

Ich denke, VonCs Antwort ist wahrscheinlich das, was Sie wollen, aber hier ist eine Möglichkeit, ein selektives "Git Apply" durchzuführen:

git show stash@{0}:MyFile.txt > MyFile.txt
Mike Monkiewicz
quelle
4
In einigen Fällen ist dies möglicherweise das, was Sie möchten. Beachten Sie jedoch, dass dieser Befehl überschrieben und nicht mit Änderungen am Arbeitsverzeichnis zusammengeführt wird.
Rhubbarb
Dies funktioniert für mich, da ich nur eine Datei kopieren wollte, die nur im Stash vorhanden ist und sich um checkoutnichts kümmert .
Tom Russell
1
Für Windows PowerShell: git show stash@`{0`}:Path/To/MyFile.txt |sc Path/To/MyFile.txt- Die Backticks sind erforderlich, damit PS die geschweiften Klammern nicht speziell interpretiert. Dies scist erforderlich, da der PS- >Operator standardmäßig UTF-16 (eigentlich UCS-2) verwendet, was wahrscheinlich nicht das ist, was Sie möchten. Die Antwort von @Balamurugan A leidet nicht unter diesen Problemen.
Ian Kemp
19

Listen Sie zuerst alle Verstecke auf

git stash list

stash@{0}: WIP on Produktkonfigurator: 132c06a5 Cursor bei glyphicon plus und close zu zeigende Hand ändern
stash@{1}: WIP on Produktkonfigurator: 132c06a5 Cursor bei glyphicon plus und close zu zeigende Hand ändern
stash@{2}: WIP on master: 7e450c81 Merge branch 'Offlineseite'

Zeigen Sie dann, welche Dateien sich im Stash befinden (wählen Sie Stash 1 aus):

git stash show 1 --name-only

//Hint: you can also write
//git stash show stash@{1} --name-only

 ajax/product.php
 ajax/productPrice.php
 errors/Company/js/offlineMain.phtml
 errors/Company/mage.php
 errors/Company/page.phtml
 js/konfigurator/konfigurator.js

Wenden Sie dann die gewünschte Datei an:

git checkout stash@{1} -- <filename>

oder ganzer Ordner:

git checkout stash@{1} /errors

Es funktioniert auch ohne, --aber es wird empfohlen, sie zu verwenden. Siehe diesen Beitrag.

Es ist auch üblich, einen doppelten Bindestrich als Signal zu erkennen, um die Optionsinterpretation zu stoppen und alle folgenden Argumente wörtlich zu behandeln.

Schwarz
quelle
1
Das ist mit dieser Bearbeitung klarer. +1
VonC
1
Ich habe viele Wege ausprobiert und dieser Weg war der, den ich brauchte. Ich hatte ein Problem, bei dem git stash popein Fehler für nicht verfolgte Dateien aufgetreten ist. Vielen Dank.
Ramin Firooz
10

Wenn Sie git stash pop(ohne Konflikte) den Stash entfernen, nachdem er angewendet wurde. Wenn Sie git stash applydies jedoch tun, wird der Patch angewendet, ohne ihn aus der Stash-Liste zu entfernen. Dann können Sie die unerwünschten Änderungen mit zurücksetzengit checkout -- files...

Ben Jackson
quelle
2
Um den Konfliktteil dieses Beitrags zu klären, müssen Sie, wenn Sie git stash popund es Konflikte gibt, diese manuell beheben, und der Stash wird NICHT entfernt.
Thomas McCabe
6

Noch ein Weg:

git diff stash@{N}^! -- path/to/file1 path/to/file2  | git apply -R
Lacho Tomov
quelle
2
Dies ist die einzig richtige Antwort IMO. Wenn Sie Ihre Datei verwenden checkoutoder showblind überschreiben, anstatt nur Änderungen zu übernehmen. "One more way" ist eine Untertreibung.
Cambunctious
1
Ich erhalte nicht das, path/to/file2was Sie gegen dieselbe Datei in Ihrem Arbeitsbereich unterscheiden möchten. Das Weglassen des zweiten Pfades funktioniert gut für mich. - Und ich erhalte eine Fehlermeldung mit der -ROption ("Patch in umgekehrter Reihenfolge anwenden", versuche die versteckte Version zu patchen?!). Meine Arbeitsversion sieht also so aus git diff stash@{N}^! -- path/to/file | git apply -.
ThomasH
"Patch fehlgeschlagen"? Versuchen Sie eine 3-Wege-Zusammenführung. ...| git apply -3 -
John Mee
6

Für Windows-Benutzer: Geschweifte Klammern haben in PowerShell eine besondere Bedeutung. Sie können entweder mit einfachen Anführungszeichen umgeben oder mit einem Backtick entkommen. Zum Beispiel:

git checkout 'stash@{0}' YourFile

Ohne sie erhalten Sie möglicherweise eine Fehlermeldung:

Unknown switch 'e'

Janac Meena
quelle
3
Volle Punktzahl für PowerShell für die am wenigsten hilfreiche Benutzermeldung, die ich diesen Monat gesehen habe.
Holdenweb