Wie würde ich eine einzelne Datei (oder Änderungen an einer Datei) aus einem Git-Stash extrahieren?

773

Ich würde gerne wissen, ob es möglich ist, eine einzelne Datei oder ein Diff einer Datei aus einem Git-Stash zu extrahieren, ohne das Stash-Änderungsset zu entfernen.

Könnte jemand dazu einige Vorschläge / Ideen machen können?

Danny
quelle

Antworten:

1130

Auf der git stash- Manpage können Sie lesen (im Abschnitt "Diskussion", direkt nach der Beschreibung "Optionen"), dass:

Ein Stash wird als Commit dargestellt, dessen Baum den Status des Arbeitsverzeichnisses aufzeichnet, und sein erstes übergeordnetes Element ist das Commit bei HEAD, als der Stash erstellt wurde.

Sie können Stash (z. B. stash@{0}das erste / oberste Stash) als Zusammenführungs-Commit behandeln und Folgendes verwenden:

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

Erläuterung: bezeichnet stash@{0}^1das erste übergeordnete Element des angegebenen Stashs. Dies ist, wie in der obigen Erläuterung angegeben, das Commit, bei dem Änderungen gespeichert wurden. Wir verwenden diese Form von "git diff" (mit zwei Commits), weil stash@{0}/ refs/stashein Merge-Commit ist, und wir müssen git mitteilen, gegen welches Elternteil wir uns unterscheiden möchten. Kryptischer:

$ git diff stash@{0}^! -- <filename>

sollte auch funktionieren ( Erläuterungen zur Syntax finden Sie in der Manpage zu git rev-rev^! parse im Abschnitt "Festlegen von Bereichen").

Ebenso können Sie git checkout verwenden , um eine einzelne Datei aus dem Vorrat zu überprüfen:

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

oder um es unter einem anderen Dateinamen zu speichern:

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

oder

$ git show stash@{0}:./<relative filename> > <newfile>

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


Möglicherweise müssen Sie vor stash@{0}Shell-Erweiterung schützen , dh verwenden "stash@{0}"oder 'stash@{0}'.

Jakub Narębski
quelle
8
Das ist ziemlich cool ... Ich habe nicht wirklich verstanden, wie Stash funktioniert, bis ich deine Antwort gelesen habe (was mich zum Git-Checkout-Zusatz führte). Ich habe das wirklich nicht verstanden, wenn Sie einen Stash machen, speichert git ZWEI Commits - einen für den Status des Index und einen für den Status der Arbeitskopie, die eine Zusammenführung zwischen dem Index und dem ursprünglichen HEAD darstellt. Dies erklärt die seltsamen Bäume, die ich gesehen habe, als ich das Repository mit "gitk --all" visualisierte, wenn Verstecke vorhanden waren.
Pat Notz
4
Meistens finde ich, dass die Git Checkout-Anwendung der beste Weg ist, um das zu erreichen, was ich tun wollte. Ich war jedoch neugierig und habe die git checkoutManpage doppelt überprüft . Die Datei kann nicht an einem anderen Speicherort abgelegt werden. Es gibt einen Verweis darauf in: stackoverflow.com/questions/888414/…
Danny
84
$ git checkout stash @ {0} - <Dateiname> ist sehr nützlich, danke
Gravitation
43
Beachten Sie, dass der git checkoutAnsatz die genaue Datei aus dem Stash kopiert - er führt sie nicht wie in Ihrem Arbeitsverzeichnis zusammen git stash apply. (Wenn Sie also Änderungen an der Basis haben, auf der der Stash erstellt wurde, gehen diese verloren).
Peterflynn
4
Beachten Sie git stash apply, dass diese Datei im Arbeitsbaum bereitgestellt werden muss, damit die Änderungen in einer Datei zusammengeführt werden können, die im Arbeitsbaum seit dem Speichern der Datei geändert wurde. Damit die automatische Zusammenführung funktioniert, können dieselben Dateien nicht sowohl in der Arbeitskopie als auch in der versteckten Kopie, die zusammengeführt werden soll, geändert werden. Schließlich entfernt Stash Apply den Artikel nicht wie gewünscht aus dem Stash git stash pop.
Ville
46

Wenn Sie git stash applyanstatt verwenden git stash pop, wird der Stash auf Ihren Arbeitsbaum angewendet, der Stash bleibt jedoch erhalten.

Nachdem dies erledigt ist, können Sie die gewünschte Datei add/ commitund die verbleibenden Änderungen zurücksetzen.

Tim Henigan
quelle
2
Um einen bestimmten Vorrat Pop: git stash pop stash@{0}(Liste der verstaute Änderungen: git stash list)
MrYoshiji
Wenn andere Dateien im Stash einen Zusammenführungskonflikt verursachen, kann ich mich mit git nicht auf die gewünschte Datei
festlegen
33

Es gibt eine einfache Möglichkeit, Änderungen von jedem Zweig zu erhalten, einschließlich Verstecken:

$ git checkout --patch stash@{0} path/to/file

Sie können die Dateispezifikation weglassen, wenn Sie in vielen Teilen patchen möchten. Oder lassen Sie den Patch (aber nicht den Pfad) weg, um alle Änderungen an einer einzelnen Datei zu erhalten. Ersetzen Sie 0durch die Stash-Nummer von git stash list, wenn Sie mehr als eine haben. Beachten Sie, dass dies so ist diffund bietet, alle Unterschiede zwischen den Zweigen anzuwenden . Schauen Sie sich an, um Änderungen von nur einem Commit / Stash zu erhalten git cherry-pick --no-commit.

Walf
quelle
Kopiert dies die genaue Datei aus dem Stash oder wird sie zusammengeführt? Wenn Sie im Falle einer Kopie Änderungen seit der Erstellung des Stashs vorgenommen haben, gehen diese verloren.
Danijel
2
@Danijel Lesen git help checkout. --patchführt interaktives Zusammenführen durch. Es wendet alle Teile an, die Sie in der Shell genehmigen (oder was auch immer Sie speichern, wenn Sie eden Patch bearbeiten möchten). Der Pfad allein überschreibt die Datei, wie ich geschrieben habe, "alle Änderungen".
Walf
1
leichte Verbesserung: git config --global alias.applydiffat '!git checkout --patch "$1" -- $(git diff --name-only "$1"^ "$1")' - Dann werden git applydiffat stash@{4}nur Dateien verwendet, die sich zwischen dem Stash und dem übergeordneten Stash geändert haben.
Markieren Sie
25

Kurze Antwort

So sehen Sie die gesamte Datei: git show stash@{0}:<filename>

Um den Unterschied zu sehen: git diff stash@{0}^1 stash@{0} -- <filename>

Luboš Turek
quelle
1
Ich glaube nicht, dass es ihm / ihr darum ging, den Stash für eine bestimmte Datei anzuzeigen - nur diese Datei zu löschen.
Amalgovinus
1
Das habe ich gesucht. Dann können Sie ersetzen diffmit difftoolIhrem Lieblings externen diff zu verwenden.
Peet Brits
19
$ git checkout stash@{0} -- <filename>

Anmerkungen:

  1. Stellen Sie sicher, dass nach dem Parameter "-" und dem Dateinamen ein Leerzeichen steht

  2. Ersetzen Sie Null (0) durch Ihre spezifische Lagernummer. Verwenden Sie:

    git stash list
    

Basierend auf Jakub Narębskis Antwort - Kürzere Version

RAM
quelle
11

Sie können den Diff für einen Stash mit " git show stash@{0}" erhalten (oder wie auch immer die Nummer des Stash lautet; siehe "Git Stash List"). Es ist einfach, den Abschnitt des Diff für eine einzelne Datei zu extrahieren.

Nathan Kitchen
quelle
2
Noch einfacher für Köpfe wie mich: Verwenden git show stashSie diese Option, um das oberste Versteck anzuzeigen (normalerweise das einzige, das Sie haben). Ebenso können Sie den Unterschied zwischen Ihrem aktuellen Zweig und dem Stash mit anzeigen git diff head stash.
Dizzley
5

Das am einfachsten zu verstehende Konzept, obwohl es vielleicht nicht das beste ist, ist, dass Sie drei Dateien geändert haben und eine Datei speichern möchten.

Wenn Sie dies tun git stash, um sie alle zu verstauen, git stash applybringen Sie sie wieder zurück und dann git checkout f.cauf die betreffende Datei, um sie effektiv zurückzusetzen.

Wenn Sie diese Datei entstapeln möchten, führen Sie a aus git reset --hardund führen Sie sie dann git stash applyerneut aus, wobei Sie die Tatsache ausnutzen, dassgit stash apply der nicht aus dem .

Philluminati
quelle
1

Wenn die versteckten Dateien mit der aktuellen Version zusammengeführt werden müssen, verwenden Sie die vorherigen Methoden mit diff. Andernfalls können Sie sie git popentstapeln, git add fileWantToKeepIhre Datei git stash save --keep-indexbereitstellen und alles außer dem, was sich auf der Bühne befindet, verstauen. Denken Sie daran, dass der Unterschied zu den vorherigen darin besteht, dass die Datei aus dem Stash "herausspringt". Die vorherigen Antworten behalten es bei, git checkout stash@{0} -- <filename>damit es Ihren Bedürfnissen entspricht.

Hola Soja Edu Feliz Navidad
quelle
0

Verwenden Sie Folgendes, um die Änderungen auf eine Datei in einem Stash auf Ihren Arbeitsbaum anzuwenden.

git diff stash^! -- <filename> | git apply

Dies ist im Allgemeinen besser als die Verwendung, git checkoutda Sie keine Änderungen verlieren, die Sie seit dem Erstellen des Stashs an der Datei vorgenommen haben.

cambunctious
quelle