git stash 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. Stashen 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.

Anlegen eines Stash deiner Arbeit

Der Befehl git stash speichert deine nicht committeten Änderungen (egal, ob sie sich in der Staging-Umgebung befinden oder nicht) zur späteren Verwendung und setzt sie dann anhand deiner Arbeitskopie zurück. Ein Beispiel:

$ git status On branch master 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 master: 5002d47 our new homepage HEAD is now at 5002d47 our new homepage $ git status On branch master nothing to commit, working tree clean

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.

Bitte beachte, dass der Stash in deinem Git-Repository ein lokaler Stash ist und deine Stashes beim Pushen nicht an den Server übermittelt werden.

Wiederanwenden deiner im Stash aufbewahrten Änderungen

Zuvor aufbewahrte Änderungen kannst du mit git stash pop erneut anwenden:

$ git status On branch master nothing to commit, working tree clean $ git stash pop On branch master 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 master Changes to be committed: new file: style.css Changes not staged for commit: modified: index.html

Das ist nützlich, wenn dieselben gestashten Änderungen auf mehrere Branches angewendet werden sollen.

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 nicht verfolgten oder ignorierten Dateien im Stash auf.

Aufnehmen von unverfolgten oder ignorierten Dateien in den 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 wurden.

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), fügt git stash die Datei nicht dem Stash hinzu.

$ script.js $ git status On branch master 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 master: 5002d47 our new homepage HEAD is now at 5002d47 our new homepage $ git status On branch master 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 master 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 master: 5002d47 our new homepage HEAD is now at 5002d47 our new homepage $ git status On branch master nothing to commit, working tree clean

Änderungen an ignorierten Dateien können miteinbezogen werden, indem du die Option -a (oder --all) an den Befehl git stash anfügst.

Git Stash – Optionen

Verwalten mehrerer Stashes

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 anzeigen. Standardmäßig werden Stashes an der Spitze des Branchs und des Commits, aus dem du den Stash erstellt hast, einfach als "WIP" (Work in Progress) angegeben. Nach einer Weile kann es schwierig werden, sich daran zu erinnern, was im jeweiligen Stash enthalten ist:

$ git stash list stash@{0}: WIP on master: 5002d47 our new homepage stash@{1}: WIP on master: 5002d47 our new homepage stash@{2}: WIP on master: 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 master: add style to our site HEAD is now at 5002d47 our new homepage $ git stash list stash@{0}: On master: add style to our site stash@{1}: WIP on master: 5002d47 our new homepage stash@{2}: WIP on master: 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 Stashs 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 @@ +

Partielle Stashes

Du kannst auch nur eine einzige Datei, mehrere Dateien auf einmal oder auch einzelne Ä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 möchtest:

$ 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 @@ + Stash this hunk [y,n,q,a,d,/,e,?]? n
Git Stash -p

Wenn du auf das ? klickst, erhältst du eine vollständige Liste der Hunk-Befehle. Diese hier sind besonders nützlich:

Befehl Beschreibung
/ Mit einem regulären Ausdruck nach einem Hunk suchen
? Hilfe
n Diesen Hunk nicht in den Stash verschieben
q Beenden (von Englisch "quit"): Alle bereits ausgewählten Hunks werden gestasht.
s Diesen Hunk in kleinere Hunks aufteilen
y 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 wird ein neuer Branch auf Basis des Commits, aus dem du deinen Stash erstellt hast, ausgecheckt, und dann werden 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 git stash verwendet, musst du hier nicht weiterlesen. Aber lies weiter, wenn dich interessiert, was bei Git (und git stash) hinter den Kulissen geschieht!

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:

$ git log --oneline --graph stash@{0} *-. 953ddde WIP on master: 5002d47 our new homepage |\ \ | | * 24b35a1 untracked files on master: 5002d47 our new homepage | * 7023dd4 index on master: 5002d47 our new homepage |/ * 5002d47 our new homepage

Je nachdem, was du stashst, werden in einem einzigen git stash-Vorgang entweder zwei oder drei neue Commits erstellt. Im Beispiel oben sind es folgende Commits:

  • stash@{0}, ein neuer Commit zum Speichern der verfolgten Dateien, die sich beim Ausführen von git stash in deiner Arbeitskopie befanden
  • Der erste übergeordnete Commit (Parent) von stash@{0}, d. h. der vorher bereits bestehende Commit, der sich am HEAD befand, als du git stash ausgeführt hast
  • Der zweite Parent von stash@{0} – ein neuer Commit, der den Index von dem Zeitpunkt repräsentiert, als du git stash ausgeführt hast
  • Der dritte Parent von stash@{0} – ein neuer Commit, der die nicht verfolgten Dateien repräsentiert, die sich in deiner Arbeitskopie befanden, als du git 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 an git stash angefügt.

So kodiert 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).

    Before stashing
  • 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 Referenz refs/stash wird aktualisiert, um auf diese Commits zu verweisen.

    Git stash
  • Mit der Option --include-untracked kannst du auch alle Änderungen an nicht verfolgten Dateien in einen weiteren Commit umkodieren.

    Git stash --include-untracked
  • Die Option --all schließt Änderungen an ignorierten Dateien genauso wie Änderungen an unverfolgten Dateien im selben Commit ein.

    Git Stash --all

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.

Möchtest du Git kennenlernen?

Sieh dir dieses interaktive Tutorial an.

Jetzt loslegen