git stash slaat (of stashes) wijzigingen die je in je werkkopie hebt aangebracht tijdelijk op, zodat je aan iets anders kunt werken, om vervolgens terug te keren en ze later opnieuw toe te passen. Stashing is handig als je snel van context moet wisselen en aan iets anders moet werken, maar je pas halverwege een codewijziging bent en nog niet helemaal klaar bent om een commit te maken.

Je werk stashen

De opdracht git stash neemt je wijzigingen waarvoor je geen commit hebt gemaakt (zowel geënsceneerd als niet opgevoerd), slaat deze op voor later gebruik en draait ze vervolgens terug van je werkkopie. Bijvoorbeeld:

$ 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

Op dit moment ben je vrij om wijzigingen aan te brengen, nieuwe commits te maken, van branches te wisselen en andere Git-bewerkingen uit te voeren. Kom vervolgens terug en pas je stash opnieuw toe wanneer je er klaar voor bent.

Merk op dat de stash lokaal is voor je Git-repository; stashes worden niet verzonden naar de server wanneer je pusht.

Je gestashte veranderingen opnieuw toepassen

Je kunt eerder gestashte wijzigingen opnieuw toepassen met git stash pop:

$ 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)

Door je stash te poppen, worden de wijzigingen uit je stash verwijderd en opnieuw toegepast op je werkkopie.

Eventueel kun je de wijzigingen ook opnieuw toepassen op uw werkkopie en ze in je stash bewaren met git stash apply:

$ git stash apply
On branch main
Changes to be committed:

    new file:   style.css

Changes not staged for commit:

    modified:   index.html

Dit is handig als u dezelfde gestashte wijzigingen op meerdere branches wilt toepassen.

Je kent nu de basis van stashing, maar er is één voorbehoud met git stash waarvan je je bewust moet zijn: Git zal standaard geen wijzigingen stashen die zijn aangebracht in niet-bijgehouden of genegeerde bestanden.

Niet-getraceerde of genegeerde bestanden stashen

Standaard zal het uitvoeren van git stash het volgende stashen:

  • wijzigingen die aan je index zijn toegevoegd (opgevoerde wijzigingen);
  • wijzigingen in bestanden die momenteel worden gevolgd door Git (niet-gestagede wijzigingen).

Maar het volgende zal niet worden gestashed:

  • nieuwe bestanden in je werkkopie die nog niet zijn opgevoerd;
  • bestanden die zijn genegeerd.

Dus als we een derde bestand aan ons voorbeeld hierboven toevoegen, maar het niet stashen (d.w.z. we voeren git add niet uit), zal git stash het niet opslaan.

$ 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

Door de optie -u (of —--nclude-untracked) toe te voegen, moet git stash ook de bestanden opslaan die je niet volgt:

$ 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

Je kunt ook wijzigingen in genegeerde bestanden toevoegen door de optie -a (of --all) door te geven wanneer git stash wordt uitgevoerd.

Git Stash-opties

Meerdere stashes beheren

Je bent niet beperkt tot één stash. Je kunt git stash meerdere keren uitvoeren om meerdere stashes te maken en vervolgens git stash list gebruiken om ze te bekijken. Standaard worden stashes eenvoudig geïdentificeerd als 'WIP' — werk in uitvoering — bovenop de branch en commit waarvan je de stash hebt gemaakt. Na een tijdje kan het moeilijk zijn om de inhoud van elke stash te onthouden:

$ 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

Om wat meer context te bieden, is het een goede gewoonte om je stashes te annoteren met een beschrijving, met behulp van git stash save 'bericht':

$ 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

Standaard past git stash pop de meest recent gemaakte stash opnieuw toe: stash@{0}

Je kunt kiezen welke stash opnieuw moet worden toegepast door de ID als laatste argument door te geven, bijvoorbeeld:

$ git stash pop stash@{2}

Verschillen in stashes bekijken

Je kunt met git stash show een samenvatting bekijken van een stash:

$ git stash show
 index.html | 1 +
 style.css | 3 +++
 2 files changed, 4 insertions(+)

Of geef de optie -p (of --patch) door om alle verschillen voor een stash te bekijken:

$ 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"/>

Gedeeltelijke stashes

Je kunt er ook voor kiezen om slechts één bestand, een verzameling bestanden of individuele wijzigingen in bestanden op te slaan. Als je de optie -p (of --patch) doorgeeft aan git stash, wordt elke gewijzigde 'hunk' in je werkkopie herhaald met de vraag of je die wilt opslaan:

$ 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
Git Stash -p

Je kunt op ? drukken voor een volledige lijst met hunk-opdrachten. De volgende zijn vaak bruikbaar:

Opdracht Beschrijving
/ zoeken naar een hunk op basis van regex
? help
N deze hunk niet stashen
Q stoppen (alle hunks die al zijn geselecteerd, worden gestashed)
S deze hunk opsplitsen in kleinere hunks
y deze hunk stashen

Er is geen expliciete 'abort'-opdracht, maar als je op CTRL-C(SIGINT) drukt, wordt het stashproces afgebroken.

Een branch maken op basis van je stash

Als de wijzigingen in je branch afwijken van de wijzigingen in je stash, kun je op conflicten stuiten bij het poppen of toepassen van uw stash. In plaats daarvan kun je git stash branch gebruiken om een nieuwe branch te maken om je gestashte wijzigingen toe te passen op:

$ 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)

Deze opdracht controleert een nieuwe branch op basis van de commit waarvan je je stash hebt gemaakt, en vervolgens worden je opgeslagen wijzigingen toegepast.

Je stash opschonen

Als je besluit dat je een bepaalde stash niet meer nodig hebt, kun je deze verwijderen met git stash drop:

$ git stash drop stash@{1}
Dropped stash@{1} (17e2697fd8251df6163117cb3d58c1f62a5e7cdb)

Je kunt ook al je stashes verwijderen met:

$ git stash clear

Zo werkt git stash

Als je gewoon wilde weten hoe je git stash moet gebruiken, kun je hier stoppen met lezen. Maar lees vooral verder als je nieuwsgierig bent naar hoe Git (en git stash) onder de motorkap werkt!

Stashes worden in je repository eigenlijk gecodeerd als commit-objecten. De speciale ref op .git/refs/stash verwijst naar je meest recent gemaakte stash, en door de reflog van de stash-ref wordt verwezen naar eerder gemaakte stashes. Daarom verwijs je naar stashes met behulp van stash@{n}: je verwijst eigenlijk naar het zoveelste reflog-item voor de stash-ref. Omdat een stash slechts een commit is, kun je het inspecteren met git log:

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

Afhankelijk van wat je hebt opgeslagen, maakt een enkele git stash-bewerking twee of drie nieuwe commits. De commits in het bovenstaande diagram zijn:

  • stash@{0}, een nieuwe commit om de bijgehouden bestanden op te slaan die in je werkkopie zaten toen je git stash uitvoerde;
  • Het eerste bovenliggende item van stash@{0}, de reeds bestaande commit die bij HEAD was toen je git stash uitvoerde;
  • Het tweede bovenliggende item van stash@{0}, een nieuwe commit die staat voor de index toen je git stash uitvoerde;
  • Het derde bovenliggende item van stash@{0}, een nieuwe commit voor de niet-bijgehouden bestanden die in je werkkopie zaten toen je git stash uitvoerde. Dit derde bovenliggende item wordt alleen gemaakt als:
    • je werkkopie eigenlijk niet-getraceerde bestanden bevatte; en
    • je de optie --include-untracked of --all hebt opgegeven toen je git stash hebt aangeroepen.

Zo codeert git stash je werkstructuur en index als commits:

  • Voordat je een stash uitvoert, kan je werkstructuur wijzigingen bevatten in bijgehouden bestanden, niet-bijgehouden bestanden en genegeerde bestanden. Sommige van deze wijzigingen kunnen ook in de index worden opgenomen.

    Voor het stashen
  • Het aanroepen van git stash codeert eventuele wijzigingen in bijgehouden bestanden als twee nieuwe commits in je DAG: één voor niet-opgevoerde wijzigingen en één voor wijzigingen die in de index zijn opgevoerd. De speciale refs/stash-ref is bijgewerkt om ernaar te verwijzen;

    git stash
  • Het gebruik van de optie --include-untracked codeert ook alle wijzigingen in niet-bijgehouden bestanden als een extra commit;

    Git stash --include-untracked
  • Het gebruik van de optie --all bevat wijzigingen in alle genegeerde bestanden naast wijzigingen in niet-bijgehouden bestanden in dezelfde commit.

    Git Stash --all

Wanneer je git stash pop uitvoert, worden de wijzigingen van de commits hierboven gebruikt om je werkkopie en index bij te werken. Ook wordt de stash-reflog 'geschud' om de popped commit te verwijderen. Merk op dat de popped commits niet onmiddellijk worden verwijderd, maar kandidaten worden voor toekomstige verwijdering.

Klaar om Git te leren?

Probeer deze interactieve tutorial.

Nu aan de slag