La reserva de canvis o stash en Git es un magatzem que permet
guardar temporalment els canvis que encara no es volen confirmar (commit).
Aquesta funció és útil si heu de realitzar alguna acció de Git que, d'altra manera,
vos faria perdre els canvis que heu realitzat al directori de treball.
Canviar de branca.
Incorporar canvis d'una altra branca (merge, rebase o pull).
La reserva de canvis permet guardar aquests canvis temporalment i recuperar-los
posteriorment quan siga necessari.
Preparació repositori
Inicialitzem un repositori amb canvis en el fitxer README.md
i una branca addicional altres_canvis on s'han fet canvis al mateix fitxer.
Danger
Crea el nou repositori en una carpeta independent per evitar
problemes amb els exemples i exercicis anteriors.
setup_stash.sh
#!/bin/bash# Elimina els repositori si existeixif[-d~/git_stash];thenrm-rf~/git_stash
fimkdir-p~/git_stash
cd~/git_stash
gitinit
gitbranch-mmain
echo"# Reserva de canvis">README.md
gitaddREADME.md
gitcommit-m"Commit inicial"gitcheckout-baltres_canvis
echo"Altres canvis">>README.md
gitcommit-a-m"Altres canvis"gitcheckoutmain
gitlga
jpuigcerver@fp:~$mkdir-p~/git_stash
jpuigcerver@fp:~$cd~/git_stash
jpuigcerver@fp:~/git_stash$gitinit
Initialized empty Git repository in ~/git_stash/.git/jpuigcerver@fp:~/git_stash(main)$gitbranch-mmain
jpuigcerver@fp:~/git_stash(main)$echo"# Reserva de canvis">README.md
jpuigcerver@fp:~/git_stash(main)$gitaddREADME.md
jpuigcerver@fp:~/git_stash(main)$gitcommit-m"Commit inicial"[main (root-commit) 5cc4104] Commit inicial 1 file changed, 1 insertion(+) create mode 100644 README.mdjpuigcerver@fp:~/git_stash(main)$gitcheckout-baltres_canvis
Switched to a new branch 'altres_canvis'jpuigcerver@fp:~/git_stash(altres_canvis)$echo"Altres canvis">>README.md
jpuigcerver@fp:~/git_stash(altres_canvis)$gitcommit-a-m"Altres canvis"[altres_canvis 602f4b0] Altres canvis 1 file changed, 1 insertion(+)jpuigcerver@fp:~/git_stash(altres_canvis)$gitcheckoutmain
Switched to branch 'main'jpuigcerver@fp:~/git_stash(main)$gitlga
*602f4b0-(0 seconds ago)Altres canvis-Joan Puigcerver(altres_canvis)*5cc4104-(0 seconds ago)Commit inicial-Joan Puigcerver(HEAD -> main)
Per què és útil git stash?
Imaginem que estem treballant en la branca principal main i hem
realitzat canvis al fitxer README.md.
Aquests canvis resideixen en el Directori de Treball i encara
no han estat confirmats (commit).
En aquest moment, podem decidir canviar a una altra branca.
En el cas que aquesta operació modifique la mateixa part
dels fitxers on hem realitzat canvis, Git ens impedirà
per no perdre aquests canvis.
jpuigcerver@fp:~/git_stash(main)$echo"Canvi A">>README.md
jpuigcerver@fp:~/git_stash(main)$gitstatus
On branch mainChanges not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory)modified: README.mdno changes added to commit (use "git add" and/or "git commit -a")jpuigcerver@fp:~/git_stash(main)$gitcheckoutaltres_canvis
error: Your local changes to the following files would be overwritten by checkout: README.mdPlease commit your changes or stash them before you switch branches.Aborting
Si llegim el missatge d'error, Git ens recomana alguna de les següents
opcions.
La primera opció és confirmar (commit) els canvis realitzats.
Això ens permetria canviar de branca sense problemes, no obstant això,
pot ser que no vulguem confirmar els canvis en aquest moment.
La segona opció és guardar els canvis de manera temporal
mitjançant la comanda git stash.
Amb l'opció -m podem afegir un missatge al stash per
identificar millor els canvis guardats.
Els canvis s'emmagatzemen de manera temporal a una pila:
Els nous canvis es guardaran a la primera posició de la pila amb l'índex 0: stash@{0}.
D'aquesta manera, els canvis més actuals es troben a la part superior
de la pila i són més fàcils d'accedir (la majoria de comandes stash
treballen per defecte amb el stash@{0}).
Figura 1. Reserva canvis amb una única entrada
L'índex dels canvis presents anteriorment a la pila incrementarà en 1.
Figura 2. Reservar canvis amb entrades existents anteriorment
Exemple: Crear una reserva de canvis
Després de guardar els canvis amb git stash, podem observar que:
Els canvis ja no es troben al Directori de Treball.
Podem canviar de branca sense problemes.
jpuigcerver@fp:~/git_stash(main)$gitstatus
On branch mainChanges not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory)modified: README.mdno changes added to commit (use "git add" and/or "git commit -a")jpuigcerver@fp:~/git_stash(main)$gitdiff
diff --git a/README.md b/README.mdindex d6704e3..e23e265 100644--- a/README.md+++ b/README.md@@ -1 +1,2 @@# Reserva de canvis
+Canvi Ajpuigcerver@fp:~/git_stash(main)$gitstash-m"Canvi A"Saved working directory and index state On main: Canvi Ajpuigcerver@fp:~/git_stash(main)$gitstatus
On branch mainnothing to commit, working tree cleanjpuigcerver@fp:~/git_stash(main)$gitcheckoutaltres_canvis
Switched to branch 'altres_canvis'jpuigcerver@fp:~/git_stash(altres_canvis)$gitcheckoutmain
Switched to branch 'main'
Exemple: Crear vàries reserves de canvis
Vegem com l'índex dels canvis incrementa en cada nova reserva.
Canvi B:
jpuigcerver@fp:~/git_stash(main)$echo"Canvi B">>README.md
jpuigcerver@fp:~/git_stash(main)$gitstash-m"Canvi B"Saved working directory and index state On main: Canvi Bjpuigcerver@fp:~/git_stash(main)$gitstatus
On branch mainnothing to commit, working tree cleanjpuigcerver@fp:~/git_stash(main)$gitstashlist
stash@{0}: On main: Canvi Bstash@{1}: On main: Canvi A
Canvi C:
jpuigcerver@fp:~/git_stash(main)$echo"Canvi C">>README.md
jpuigcerver@fp:~/git_stash(main)$gitstash-m"Canvi C"Saved working directory and index state On main: Canvi Cjpuigcerver@fp:~/git_stash(main)$gitstatus
On branch mainnothing to commit, working tree cleanjpuigcerver@fp:~/git_stash(main)$gitstashlist
stash@{0}: On main: Canvi Cstash@{1}: On main: Canvi Bstash@{2}: On main: Canvi A
Els canvis reservats poden recuperar-se mitjançant l'acció apply.
gitstashapply[index]
Aquesta acció aplicarà els canvis guardats al directori de treball.
També es pot indicar l'índex del stash que es vol aplicar. Si no s'indica,
s'aplicarà per defecte el stash@{0}.
Figura 3. Recuperar canvis amb stash apply
Exemple: Recuperar els canvis amb apply
jpuigcerver@fp:~/git_stash(main)$gitstatus
On branch mainnothing to commit, working tree cleanjpuigcerver@fp:~/git_stash(main)$gitstashapply
On branch mainChanges not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory)modified: README.mdno changes added to commit (use "git add" and/or "git commit -a")jpuigcerver@fp:~/git_stash(main)$gitstatus
On branch mainChanges not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory)modified: README.mdno changes added to commit (use "git add" and/or "git commit -a")jpuigcerver@fp:~/git_stash(main)$gitdiff
diff --git a/README.md b/README.mdindex d6704e3..208685c 100644--- a/README.md+++ b/README.md@@ -1 +1,2 @@# Reserva de canvis
+Canvi Cjpuigcerver@fp:~/git_stash(main)$gitstashlist
stash@{0}: On main: Canvi Cstash@{1}: On main: Canvi Bstash@{2}: On main: Canvi A
Si a més, volem esborrar la reserva de canvis, podem utilitzar l'opció pop.
gitstashpop[index]
Figura 4. Recuperar canvis i esborrar la reserva amb stash pop
Exemple: Recuperar els canvis amb pop
jpuigcerver@fp:~/git_stash(main)$gitrestoreREADME.md# (1)!jpuigcerver@fp:~/git_stash(main)$gitstatus
On branch mainnothing to commit, working tree cleanjpuigcerver@fp:~/git_stash(main)$gitstashpop
On branch mainChanges not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: README.mdno changes added to commit (use "git add" and/or "git commit -a")Dropped refs/stash@{0} (5421da4ebcbd229b003f105eeefea1b6cfa13f3e)jpuigcerver@fp:~/git_stash(main)$gitstatus
On branch mainChanges not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory)modified: README.mdno changes added to commit (use "git add" and/or "git commit -a")jpuigcerver@fp:~/git_stash(main)$gitdiff
diff --git a/README.md b/README.mdindex d6704e3..208685c 100644--- a/README.md+++ b/README.md@@ -1 +1,2 @@# Reserva de canvis
+Canvi Cjpuigcerver@fp:~/git_stash(main)$gitstashlist
stash@{0}: On main: Canvi Bstash@{1}: On main: Canvi A
Descartem els canvis del Directori de Treball que
teníem de l'exemple anterior.
Una reserva de canvis pot ser eliminada de la pila de canvis mitjançant
l'acció drop.
gitstashdrop[index]
També es pot indicar l'índex del stash que es vol descartar. Si no s'indica,
es descartarà per defecte el stash@{0}.
Exemple: Descartar els canvis
jpuigcerver@fp:~/git_stash(main)$gitstashlist
stash@{0}: On main: Canvi Bstash@{1}: On main: Canvi Ajpuigcerver@fp:~/git_stash(main)$gitstashdrop
Dropped refs/stash@{0} (a1be7febfb9e812173942ae63be37375e8d27d13)jpuigcerver@fp:~/git_stash(main)$gitstashlist
stash@{0}: On main: Canvi A
📌 Aquest document pot quedar desactualitzat després d’imprimir-lo. Pots consultar la versió més recent
a la pàgina web.
🌿 Abans d’imprimir aquest document, considera si és realment necessari. Redueix el consum de paper i ajuda a protegir el nostre entorn.