git stash – Tutorial
Der git stash
-Code bewirkt, dass Änderungen an deiner Arbeitskopie zeitweise zurückgestellt (oder auch gestasht) werden, damit du dich anderen Aufgaben widmen und die Änderungen später aufspielen kannst. Die Verwendung von "git stash" kann praktisch sein, wenn du mitten in einer Codeänderung steckst, zum Committen aber noch nicht bereit bist und schnell an etwas ganz Anderem weiterarbeiten musst.
- Git stash
- Anlegen eines Stash mit "git stash"
- Im Stash aufbewahrte Änderungen mit "git stash" wieder anwenden
- Aufnehmen von unverfolgten oder ignorierten Dateien mit "git stash"
- Verwalten mehrerer Stashes mit "git stash"
- Ansehen von Stash-Diffs
- Partielle Stashes
- Erstellen eines Branch von deinem Stash
- Bereinigen des Stash
- Funktionsweise von git stash
Anlegen eines Stash mit "git stash"
Der git stash
-Code speichert deine nicht committeten Änderungen (egal, ob sie sich in der Staging-Umgebung befinden oder nicht) zur späteren Verwendung und setzt dann deine Arbeitskopie zurück. Ein Beispiel:
$ git status
On branch main
Changes to be committed:
new file: style.css
Changes not staged for commit:
modified: index.html
$ git stash
Saved working directory and index state WIP on main: 5002d47 our new homepage
HEAD is now at 5002d47 our new homepage
$ git status
On branch main
nothing to commit, working tree clean
Zugehöriges Material
git branch
Lösung anzeigen
Git kennenlernen mit Bitbucket Cloud
Nun kannst du Änderungen vornehmen, neue Commits erstellen, Branches wechseln und alle anderen Git-Funktionen nutzen. Wenn du schließlich bereit bist, wendest du deinen Stash wieder an.
Beachte, dass das in deinem Git-Repository ein lokaler Stash ist und deine Stashes beim Pushen nicht an den Server übermittelt werden.
Im Stash aufbewahrte Änderungen mit "git stash" wieder anwenden
Zuvor aufbewahrte Änderungen kannst du mit git stash pop
erneut anwenden:
$ git status
On branch main
nothing to commit, working tree clean
$ git stash pop
On branch main
Changes to be committed:
new file: style.css
Changes not staged for commit:
modified: index.html
Dropped refs/stash@{0} (32b3aa1d185dfe6d57b3c3cc3b32cbf3e380cc6a)
Wenn du deinen Stash poppst, werden die Änderungen aus deinem Stash entfernt und erneut auf deine Arbeitskopie angewendet.
Du kannst aber auch die Änderungen erneut auf deine Arbeitskopie anwenden und sie weiterhin in deinem Stash aufbewahren. Hierfür gibst du git stash apply
ein:
$ git stash apply
On branch main
Changes to be committed:
new file: style.css
Changes not staged for commit:
modified: index.html
Das ist nützlich, wenn du dieselben gestashten Änderungen auf mehrere Branches anwenden willst.
Nachdem du nun die Grundlagen zum Stashing kennst, solltest du dir noch über einen kleinen Nachteil von git stash
bewusst werden: In den Standardeinstellungen bewahrt Git keine Änderungen an u nicht verfolgten oder ignorierten Dateien im Stash auf.
Aufnehmen von unverfolgten oder ignorierten Dateien mit "git stash"
In den Standardeinstellungen wird beim Ausführen von git stash
Folgendes in den Stash verschoben:
- Änderungen, die deinem Index hinzugefügt wurden (in der Staging-Umgebung)
- Änderungen an Dateien, die aktuell von Git verfolgt werden (noch nicht in der Staging-Umgebung)
Nicht in den Stash verschoben wird Folgendes:
- Neue Dateien in deiner Arbeitskopie, die sich noch nicht in der Staging-Umgebung befinden
- Dateien, die ignoriert werden
Wenn wir also dem obigen Beispiel eine dritte Datei hinzufügen, diese aber nicht in die Staging-Umgebung verschieben (d. h. wir führen git add
nicht aus), wird git stash
die Datei nicht dem Stash hinzufügen.
$ script.js
$ git status
On branch main
Changes to be committed:
new file: style.css
Changes not staged for commit:
modified: index.html
Untracked files:
script.js
$ git stash
Saved working directory and index state WIP on main: 5002d47 our new homepage
HEAD is now at 5002d47 our new homepage
$ git status
On branch main
Untracked files:
script.js
Durch Hinzufügen der Option -u
(oder --include-untracked
) werden mit git stash
auch deine nicht verfolgten Daten gestasht:
$ git status
On branch main
Changes to be committed:
new file: style.css
Changes not staged for commit:
modified: index.html
Untracked files:
script.js
$ git stash -u
Saved working directory and index state WIP on main: 5002d47 our new homepage
HEAD is now at 5002d47 our new homepage
$ git status
On branch main
nothing to commit, working tree clean
Die Änderungen ignorierter Dateien können miteinbezogen werden, indem du die Option -a
(oder --all
) an den Befehl git stash
anfügst.
Verwalten mehrerer Stashes mit "git stash"
Du musst dich nicht auf einen einzigen Stash beschränken. Du kannst git stash
mehrmals ausführen, um mehrere Stashes zu erstellen und diese anschließend mit git stash list
ansehen. Standardmäßig werden Stashes an der Spitze des Branch und Commits, von dem du den Stash erstellt hast, einfach als "WIP", also Work in Progress, identifiziert. Nach einer Weile kann es schwierig werden, sich daran zu erinnern, was in dem jeweiligen Stash enthalten ist:
$ git stash list
stash@{0}: WIP on main: 5002d47 our new homepage
stash@{1}: WIP on main: 5002d47 our new homepage
stash@{2}: WIP on main: 5002d47 our new homepage
Zur Bereitstellung von mehr Kontextinformationen ist es sinnvoll, deine Stashes mithilfe von git stash save "Nachricht"
mit einer Beschreibung zu versehen:
$ git stash save "add style to our site"
Saved working directory and index state On main: add style to our site
HEAD is now at 5002d47 our new homepage
$ git stash list
stash@{0}: On main: add style to our site
stash@{1}: WIP on main: 5002d47 our new homepage
stash@{2}: WIP on main: 5002d47 our new homepage
Standardmäßig wird mit git stash pop
der zuletzt erstellte Stash erneut angewendet: stash@{0}
Du kannst aber wählen, welcher Stash erneut angewendet werden soll, indem du dessen Kennung als letztes Argument anfügst, z. B.:
$ git stash pop stash@{2}
Ansehen von Stash-Diffs
Mit git stash show
wird eine Zusammenfassung für einen Stash angezeigt:
$ git stash show
index.html | 1 +
style.css | 3 +++
2 files changed, 4 insertions(+)
Du kannst aber auch die Option -p
(oder --patch
) angeben, um den vollständigen Diff eines Stashes anzuzeigen:
$ git stash show -p
diff --git a/style.css b/style.css
new file mode 100644
index 0000000..d92368b
--- /dev/null
+++ b/style.css
@@ -0,0 +1,3 @@
+* {
+ text-decoration: blink;
+}
diff --git a/index.html b/index.html
index 9daeafb..ebdcbd2 100644
--- a/index.html
+++ b/index.html
@@ -1 +1,2 @@
+<link rel="stylesheet" href="style.css"/>
Partielle Stashes
Du kannst auch nur eine einzige Datei, mehrere Dateien oder auch beliebige Änderungen aus Dateien stashen. Wenn du die Option -p
(oder --patch
) für git stash
angibst, wird der Befehl für jeden geänderten "Hunk" in deiner Arbeitskopie wiederholt und du musst angeben, ob du ihn stashen willst:
$ git stash -p
diff --git a/style.css b/style.css
new file mode 100644
index 0000000..d92368b
--- /dev/null
+++ b/style.css
@@ -0,0 +1,3 @@
+* {
+ text-decoration: blink;
+}
Stash this hunk [y,n,q,a,d,/,e,?]? y
diff --git a/index.html b/index.html
index 9daeafb..ebdcbd2 100644
--- a/index.html
+++ b/index.html
@@ -1 +1,2 @@
+<link rel="stylesheet" href="style.css"/>
Stash this hunk [y,n,q,a,d,/,e,?]? n
Wenn du auf das ? klickst, erhältst du eine vollständige Liste der Hunk-Befehle. Diese hier sind besonders nützlich:
Befehl | Beschreibung |
---|---|
/ | Beschreibung Suche nach einem Hunk mit einem regulären Ausdruck |
? | Beschreibung Hilfe |
n | Beschreibung Diesen Hunk nicht in den Stash verschieben |
q | Beschreibung beenden (von Englisch "quit"): Alle bereits ausgewählten Hunks werden gestasht. |
s | Beschreibung Diesen Hunk in kleinere Hunks aufteilen |
y | Beschreibung Diesen Hunk in den Stash verschieben |
Es gibt zwar keinen ausdrücklichen Befehl zum "Abbrechen", aber mit Strg-C
(SIGINT) kannst du den Stash-Prozess abbrechen.
Erstellen eines Branch von deinem Stash
Wenn die Änderungen an deinem Branch von den Änderungen in deinem Stash abweichen, kann es zu Konflikten kommen, wenn du deinen Stash anwendest. Stattdessen kannst du mit git stash branch
einen neuen Branch erstellen, auf den du die Änderungen aus deinem Stash anwendest:
$ git stash branch add-stylesheet stash@{1}
Switched to a new branch 'add-stylesheet'
On branch add-stylesheet
Changes to be committed:
new file: style.css
Changes not staged for commit:
modified: index.html
Dropped refs/stash@{1} (32b3aa1d185dfe6d57b3c3cc3b32cbf3e380cc6a)
Hiermit werden ein neuer Branch auf Basis des Commits, auf dem du deinen Stash erstellt hast, ausgecheckt und dann die aufbewahrten Änderungen eingefügt.
Bereinigen des Stash
Wenn du einen bestimmten Stash nicht mehr benötigst, kannst du ihn mit git stash drop
löschen:
$ git stash drop stash@{1}
Dropped stash@{1} (17e2697fd8251df6163117cb3d58c1f62a5e7cdb)
Oder du löschst alle deine Stashes mit:
$ git stash clear
Funktionsweise von git stash
Wenn du lediglich wissen wolltest, wie man den git stash
-Code verwendet, brauchst du ab hier nicht weiterzulesen. Wenn es dich aber interessiert, was bei Git (und git stash
) hinter den Kulissen passiert, dann solltest du dieses "git stash"-Tutorial unbedingt weiterlesen!
Stashes sind übrigens in deinem Repository als Commit kodiert. Die spezielle Referenz .git/refs/stash
verweist auf deinen zuletzt erstellten Stash, früher erstellte Stashes werden über das Reflog der stash
-Referenz referenziert. Deshalb referenzierst du Stashes über stash@{n}:
Du referenzierst eigentlich den n-ten Reflog-Eintrag für den stash
. Da ein Stash einfach ein Commit ist, kannst du ihn mit git log
untersuchen:
Je nachdem, was du stashst, werden in einem einzigen git stash
-Vorgang entweder zwei oder drei neue Commits durchgeführt. Im Beispiel oben gibt es folgende Commits:
stash@{0}
, ein neuer Commit zum Speichern der verfolgten Dateien, die sich beim Ausführen vongit stash
in deiner Arbeitskopie befanden- Der erste übergeordnete Commit von
stash@{0}
, d. h. der vorher bereits bestehende Commit, der sich am HEAD befand, als dugit stash
ausgeführt hast - Der zweite Parent von
stash@{0}
, ein neuer Commit, der den Index von dem Zeitpunkt repräsentiert, als dugit stash
ausgeführt hast - Der dritte Parent von
stash@{0}
, ein neuer Commit, der die unverfolgten Dateien repräsentiert, die sich in deiner Arbeitskopie befanden, als dugit stash
ausgeführt hast. Der dritte Parent wird nur unter folgenden Voraussetzungen erstellt:- Deine Arbeitskopie enthält unverfolgte Dateien und
- du hast die Option
--include-untracked
oder--all
angit stash
angefügt.
So codierst du mit git stash
deinen Arbeitsbaum und deinen Index in Commits um:
- Vor dem Stashing kann dein Arbeitsbaum Änderungen an verfolgten, nicht verfolgten und ignorierten Dateien enthalten. Einige dieser Änderungen befinden sich ggf. auch im Index (in der Staging-Umgebung).
- Bei der Verwendung von
git stash
werden alle Änderungen an verfolgten Dateien als zwei neue Commits in deinem DAG (gerichteten azyklischen Graphen) kodiert: ein Commit für die Änderungen, die sich nicht in der Staging-Umgebung befinden und ein Commit, für die Änderungen, die sich in der Staging-Umgebung (Index) befinden. Die spezielle Referenzrefs/stash
wird aktualisiert, um auf diese Commits zu verweisen.
- Mit der Option
--include-untracked
kannst du auch alle Änderungen an nicht verfolgten Dateien in einen weiteren Commit umkodieren.
- Die Option
--all
schließt Änderungen an ignorierten Dateien genauso wie Änderungen an unverfolgten Dateien im selben Commit ein.
Wenn du git stash pop
ausführst, werden die Änderungen aus den obigen Commits zur Aktualisierung deiner Arbeitskopie und deines Index verwendet und der hervorgeholte Commit wird aus dem Stash-Reflog entfernt. Beachte, dass die hervorgeholten Commits nicht sofort gelöscht werden, sondern zu Kandidaten für die nächste Bereinigung werden.
Diesen Artikel teilen
Nächstes Thema
Lesenswert
Füge diese Ressourcen deinen Lesezeichen hinzu, um mehr über DevOps-Teams und fortlaufende Updates zu DevOps bei Atlassian zu erfahren.