Beachten Sie als zusätzliche Erklärung, dass git stashentweder zwei oder drei Festschreibungen vorgenommen werden. Der Standardwert ist zwei; Sie erhalten drei, wenn Sie die Schreibweise der Optionen --alloder 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 ifür den Inhalt des Index- / Staging-Bereichs und wfü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 iCommit 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 stasherstellen, wkopiert der Code jetzt alle nachverfolgten Arbeitsbaumdateien (in einen temporären Hilfsindex). Git setzt das erste übergeordnete wElement dieses Commits auf das HEADCommit und das zweite übergeordnete Element auf das Commit i. Zuletzt wird stashauf dieses wCommit hingewiesen:
...--o--o--o <-- branch (HEAD)
|\
i-w <-- stash
Wenn Sie --include-untrackedoder hinzufügen --all, macht Git uzwischen dem Erstellen von iund ein zusätzliches Commit w. Der Snapshot-Inhalt für usind 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 uCommit hat kein übergeordnetes Element. Wenn es dann erstellt git stashwird w, wird wdas dritte übergeordnete Element für dieses uCommit 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 ubegehen (mit , git cleandas 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 applydas Festschreiben vollständig ignoriert i.
Wenn der Stash nur zwei Commits hat, git stash applykann das wCommit jetzt angewendet werden . Es tut dies durch Aufrufe von git merge2 (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 ( is Elternteil, und w"erste Mutter s) als merge Base, wwie die --theirsCommit, 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 applyselbst ist erfolgreich. Wenn Sie verwendet git stash popdie 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 popDer 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 udas von Ihnen angewendete Stash ein Commit enthält - ändern sich die Dinge! Es gibt keine Möglichkeit, so zu tun, als ob das uCommit nicht existiert. 4 Git besteht darauf, alle Dateien aus diesem uCommit in den aktuellen Arbeitsbaum zu extrahieren . Dies bedeutet, dass die Dateien entweder überhaupt nicht vorhanden sein dürfen oder denselben Inhalt wie beim uFestschreiben haben dürfen.
Um dies zu erreichen, können Sie sich git cleanselbst 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 -uoder git stash save -a, da diese git cleanfür Sie ausgeführt werden. Aber das lässt Sie nur mit einem anderen uStash 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 stashCode wird git merge-recursivehier 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 branchalles perfekt wiederherstellen können. Nun, vorausgesetzt, das Fehlen dieses lästigen uCommits.
4 Es sollte wirklich geben: git stash apply --skip-untrackedoder so. Es sollte auch eine Variante geben, die bedeutet, dass alle diese uFestschreibungsdateien in einem neuen Verzeichnis abgelegt werden , z git stash apply --untracked-into <dir>. B. vielleicht.
git stash show -p | git apply --3