Beachten Sie als zusätzliche Erklärung, dass git stash
entweder zwei oder drei Festschreibungen vorgenommen werden. Der Standardwert ist zwei; Sie erhalten drei, wenn Sie die Schreibweise der Optionen --all
oder verwenden --include-untracked
.
Diese zwei oder drei Commits sind in einer wichtigen Hinsicht besonders: Sie befinden sich in keinem Zweig. Git findet sie über den speziellen Namen stash
. 1 Das Wichtigste ist jedoch, was Git Ihnen mit diesen zwei oder drei Commits ermöglicht - und bringt . Um dies zu verstehen, müssen wir uns ansehen, was in diesen Commits enthalten ist.
Was ist in einem Vorrat
Jedes Commit kann ein oder mehrere übergeordnete Commits auflisten. Diese bilden ein Diagramm, in dem spätere Festschreibungen auf frühere verweisen. Der Stash enthält normalerweise zwei Commits, die ich gerne i
für den Inhalt des Index- / Staging-Bereichs und w
für den Inhalt des Arbeitsbaums aufrufe. Denken Sie auch daran, dass jedes Commit einen Snapshot enthält. Bei einem normalen Commit wird dieser Snapshot aus dem Inhalt des Index- / Staging-Bereichs erstellt. Das i
Commit ist also in der Tat ein ganz normales Commit! Es ist einfach nicht auf einem Zweig:
...--o--o--o <-- branch (HEAD)
|
i
Wenn Sie einen normalen Stash git stash
erstellen, w
kopiert der Code jetzt alle nachverfolgten Arbeitsbaumdateien (in einen temporären Hilfsindex). Git setzt das erste übergeordnete w
Element dieses Commits auf das HEAD
Commit und das zweite übergeordnete Element auf das Commit i
. Zuletzt wird stash
auf dieses w
Commit hingewiesen:
...--o--o--o <-- branch (HEAD)
|\
i-w <-- stash
Wenn Sie --include-untracked
oder hinzufügen --all
, macht Git u
zwischen dem Erstellen von i
und ein zusätzliches Commit w
. Der Snapshot-Inhalt für u
sind Dateien, die nicht verfolgt, aber nicht ignoriert werden ( --include-untracked
), oder Dateien, die nicht verfolgt werden, selbst wenn sie ignoriert werden ( --all
). Dieses zusätzliche u
Commit hat kein übergeordnetes Element. Wenn es dann erstellt git stash
wird w
, wird w
das dritte übergeordnete Element für dieses u
Commit festgelegt, sodass Sie Folgendes erhalten:
...--o--o--o <-- branch (HEAD)
|\
i-w <-- stash
/
u
Git auch an dieser Stelle, entfernt alle Arbeit Baum - Dateien , die in der Liquidation u
begehen (mit , git clean
das zu tun).
Ein Versteck wiederherstellen
Wenn Sie einen Stash wiederherstellen , haben Sie die Möglichkeit --index
, ihn zu verwenden oder nicht zu verwenden. Dies teilt git stash apply
(oder einem der intern verwendeten Befehle apply
, z. B. pop
) mit, dass das Commit verwendet werden soll ,i
um zu versuchen, Ihren aktuellen Index zu ändern. Diese Änderung erfolgt mit:
git diff <hash-of-i> <hash-of-i's-parent> | git apply --index
(mehr oder weniger; es gibt eine Reihe von Details, die der Grundidee hier im Wege stehen).
Wenn Sie dies weglassen --index
, wird git stash apply
das Festschreiben vollständig ignoriert i
.
Wenn der Stash nur zwei Commits hat, git stash apply
kann das w
Commit jetzt angewendet werden . Es tut dies durch Aufrufe von git merge
2 (ohne dass es das Ergebnis als eine normale merge zu begehen oder zu behandeln), auf das die ursprünglichen commit Verwendung der Vorrat hergestellt wurde ( i
s Elternteil, und w
"erste Mutter s) als merge Base, w
wie die --theirs
Commit, und Ihr aktuelles (HEAD) Commit als Ziel der Zusammenführung. Wenn die Zusammenführung erfolgreich ist, ist alles in Ordnung - zumindest glaubt Git das - und das git stash apply
selbst ist erfolgreich. Wenn Sie verwendet git stash pop
die Stash anwenden, wird der Code jetzt fällt das Versteck. 3 Wenn die Zusammenführung fehlschlägt, erklärt Git, dass die Anwendung fehlgeschlagen ist. Wenn du benutzt hastgit stash pop
Der Code behält den Stash bei und liefert den gleichen Fehlerstatus wie für git stash apply
.
Aber wenn Sie dieses dritte Commit haben - wenn u
das von Ihnen angewendete Stash ein Commit enthält - ändern sich die Dinge! Es gibt keine Möglichkeit, so zu tun, als ob das u
Commit nicht existiert. 4 Git besteht darauf, alle Dateien aus diesem u
Commit in den aktuellen Arbeitsbaum zu extrahieren . Dies bedeutet, dass die Dateien entweder überhaupt nicht vorhanden sein dürfen oder denselben Inhalt wie beim u
Festschreiben haben dürfen.
Um dies zu erreichen, können Sie sich git clean
selbst verwenden - aber denken Sie daran, dass nicht verfolgte Dateien (ignoriert oder nicht) keine andere Existenz in einem Git-Repository haben. Stellen Sie also sicher, dass diese Dateien alle zerstört werden können! Sie können auch ein temporäres Verzeichnis erstellen und die Dateien zur sicheren Aufbewahrung dorthin verschieben - oder sogar ein anderes git stash save -u
oder git stash save -a
, da diese git clean
für Sie ausgeführt werden. Aber das lässt Sie nur mit einem anderen u
Stash zurück, mit dem Sie sich später befassen müssen.
1 Das ist in der Tat refs/stash
. Dies ist wichtig, wenn Sie einen Zweig mit dem Namen erstellen stash
: Der vollständige Name des Zweigs lautet refs/heads/stash
, sodass diese nicht in Konflikt stehen. Aber tu das nicht: Git macht es nichts aus, aber du wirst dich verwirren. :-)
2 Der git stash
Code wird git merge-recursive
hier tatsächlich direkt verwendet . Dies ist aus mehreren Gründen erforderlich und hat auch den Nebeneffekt, dass Git es nicht als Zusammenführung behandelt, wenn Sie Konflikte lösen und festschreiben.
3 Deshalb empfehle ich git stash pop
, zugunsten von zu vermeiden git stash apply
. Sie haben die Möglichkeit zu überprüfen, was angewendet wurde, und zu entscheiden, ob es tatsächlich richtig angewendet wurde. Wenn nicht, haben Sie immer noch Ihren Vorrat, was bedeutet, dass Sie git stash branch
alles perfekt wiederherstellen können. Nun, vorausgesetzt, das Fehlen dieses lästigen u
Commits.
4 Es sollte wirklich geben: git stash apply --skip-untracked
oder so. Es sollte auch eine Variante geben, die bedeutet, dass alle diese u
Festschreibungsdateien in einem neuen Verzeichnis abgelegt werden , z git stash apply --untracked-into <dir>
. B. vielleicht.
git stash show -p | git apply --3