Close

Git stash

git stash esegue lo shelve temporaneamente (o accantona) le modifiche apportate alla copia di lavoro per consentirti di lavorare su qualcos'altro e di tornare poi indietro e riapplicarle in un secondo momento. L'accantonamento è utile se devi cambiare rapidamente contesto e lavorare su qualcos'altro, ma sei a metà di una modifica del codice e non sei ancora pronto per il commit.


Accantonamento del lavoro


Il comando git stash prende le modifiche non sottoposte a commit (sia preparate che non preparate per il commit), le salva per un uso futuro e poi le ripristina dalla copia di lavoro. Ad esempio:

$ 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
Branch Git
materiale correlato

Branch Git

Logo di Bitbucket
Scopri la soluzione

Impara a utilizzare Git con Bitbucket Cloud

A questo punto puoi apportare modifiche, creare nuovi commit, passare da un branch all'altro ed eseguire qualsiasi altra operazione Git; quindi, puoi tornare indietro e riapplicare l'accantonamento quando preferisci.

Nota che l'accantonamento si trova in locale nel repository Git; gli accantonamenti non vengono trasferiti sul server quando esegui il push.

Riapplicazione delle modifiche accantonate


Puoi riapplicare le precedenti modifiche accantonate utilizzando 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)

Il prelievo dell'accantonamento rimuove le modifiche da quest'ultimo e le riapplica alla copia di lavoro.

In alternativa, puoi riapplicare le modifiche alla copia di lavoro e conservarle nell'accantonamento con il comando 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

Questa procedura è utile se desideri applicare le stesse modifiche accantonate a più branch.

Ora che conosci le basi dell'accantonamento, occorre fare una precisazione su git stash: per impostazione predefinita, Git non accantonerà le modifiche apportate ai file non monitorati o ignorati.

Accantonamento dei file non monitorati o ignorati


Per impostazione predefinita, l'esecuzione di git stash accantonerà:

  • modifiche aggiunte all'indice (modifiche preparate per il commit)
  • modifiche apportate ai file attualmente monitorati da Git (modifiche non preparate per il commit)

Ma non accantonerà:

  • nuovi file nella copia di lavoro che non sono stati ancora preparati per il commit
  • file ignorati

Quindi, se aggiungiamo un terzo file al nostro esempio precedente, ma non lo prepariamo per il commit (ad es. non eseguiamo git add), git stash non lo accantonerà.

$ 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

L'aggiunta dell'opzione -u (o --include-untracked) dice a git stash di accantonare anche i file non monitorati:

$ 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

Puoi includere anche le modifiche ai file ignorati inviando l'opzione -a (o --all) quando esegui git stash.

Opzioni di git stash

Gestione di più accantonamenti


Non sei limitato a un solo accantonamento. Puoi eseguire git stash più volte per creare più accantonamenti e quindi usare git stash list per visualizzarli. Per impostazione predefinita, gli accantonamenti sono identificati semplicemente come "WIP" (lavoro in corso) in cima al branch e al commit da cui hai creato l'accantonamento. Dopo un po', può essere difficile ricordare i contenuti di ciascun accantonamento:

$ 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

Per fornire un po' più di contesto, è buona norma aggiungere una descrizione agli accantonamenti, usando git stash save "message":

$ 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

Per impostazione predefinita, git stash pop riapplicherà l'accantonamento creato più di recente: stash@ {0}

Puoi scegliere quale accantonamento riapplicare inviando il relativo identificatore come ultimo argomento, ad esempio:

$ git stash pop stash@{2}

Visualizzazione delle differenze tra gli accantonamenti


Puoi visualizzare un riepilogo di un accantonamento con git stash show:

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

Oppure, puoi inviare l'opzione -p (o --patch) per visualizzare le differenze complete di un accantonamento:

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

Accantonamenti parziali


Puoi inoltre scegliere di accantonare un singolo file, una raccolta di file o singole modifiche all'interno dei file. Se invii l'opzione -p (o --patch) a git stash, il comando scorrerà ogni "hunk" modificato nella copia di lavoro e ti chiederà se desideri accantonarlo:

$ 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

Puoi premere ? per un elenco completo dei comandi di hunk. Quelli più utili sono:

Comando

Descrizione

/

Descrizione

cerca un hunk in base all'espressione regolare

?

Descrizione

assistenza

n

Descrizione

non accantonare questo hunk

q

Descrizione

esci (tutti gli hunk che sono già stati selezionati verranno accantonati)

s

Descrizione

dividi questo hunk in hunk più piccoli

y

Descrizione

accantona questo hunk

Non esiste un comando "abort" esplicito, ma se premi CTRL-C(SIGINT) il processo di accantonamento verrà interrotto.

Creazione di un branch dall'accantonamento


Se le modifiche sul branch divergono da quelle nell'accantonamento, potresti incorrere in conflitti quando prelevi o applichi l'accantonamento. In alternativa, puoi usare git stash branch per creare un nuovo branch a cui applicare le modifiche accantonate:

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

Esegue il checkout di un nuovo branch in base al commit da cui hai creato l'accantonamento, quindi vi inserisce le modifiche accantonate.

Pulizia dell'accantonamento


Se decidi che non ti serve più un determinato accantonamento, puoi eliminarlo con git stash drop:

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

Oppure puoi eliminare tutti gli accantonamenti con:

$ git stash clear

Come funziona git stash


Se vuoi solo sapere come usare git stash, puoi fermarti qui, senza leggere oltre. Ma se ti incuriosisce conoscere il funzionamento interno di Git (e di git stash), continua a leggere.

Gli accantonamenti sono in realtà codificati nel repository sotto forma di oggetti di commit. Il riferimento speciale in .git/refs/stash punta all'accantonamento creato più di recente e gli accantonamenti creati in precedenza sono riportati nel log di riferimento del riferimento di stash. Questo è il motivo per cui si fa riferimento agli accantonamenti con stash@{n}: in realtà si fa riferimento all'ennesima voce del log di riferimento relativa al riferimento di stash. Dal momento che un accantonamento è semplicemente un commit, puoi ispezionarlo con git log:

A seconda degli elementi che hai accantonato, una singola operazione git stash crea due o tre nuovi commit. I commit nel diagramma riportato sopra sono:

  • stash@{0}, un nuovo commit per archiviare i file monitorati che erano nella copia di lavoro quando hai eseguito git stash
  • Il primo elemento principale di stash@{0}, il commit preesistente che si trovava su HEAD quando hai eseguito git stash
  • Il secondo elemento principale di stash@{0}, un nuovo commit che rappresentava l'indice quando hai eseguito git stash
  • Il terzo elemento principale di stash@{0}, un nuovo commit che rappresenta i file non monitorati che erano nella copia di lavoro quando hai eseguito git stash. Questo terzo elemento principale è stato creato solo se:
    • la copia di lavoro conteneva effettivamente file non monitorati; e
    • hai specificato l'opzione --include-untracked o --all quando hai richiamato git stash.

In che modo git stash codifica la struttura di lavoro e l'indice sotto forma di commit:

  • Prima dell'accantonamento, la struttura di lavoro può contenere le modifiche ai file monitorati, non monitorati e ignorati. Alcune di queste modifiche possono inoltre essere preparate per il commit nell'indice.
Prima dell'accantonamento
  • Richiamando git stash, vengono codificate tutte le modifiche ai file monitorati come due nuovi commit nel DAG: uno per le modifiche non preparate per il commit e uno per le modifiche preparate per il commit nell'indice. Il riferimento refs/stash speciale viene aggiornato in modo da puntare a queste ultime.
Git stash
  • L'uso dell'opzione --include-untracked consente di codificare anche le eventuali modifiche ai file non monitorati come commit aggiuntivo.
Git stash --include-untracked
  • L'uso dell'opzione --all include le modifiche a tutti i file ignorati e le modifiche ai file non monitorati nello stesso commit.
Git stash --all

Quando esegui git stash pop, le modifiche provenienti dai commit riportati sopra vengono utilizzate per aggiornare la copia di lavoro e l'indice e il log di riferimento dell'accantonamento viene riordinato in modo da rimuovere il commit prelevato. Nota che i commit prelevati non vengono eliminati immediatamente, ma vengono tenuti da parte per un possibile uso nella futura garbage collection.


Condividi l'articolo
Argomento successivo

Letture consigliate

Aggiungi ai preferiti queste risorse per ricevere informazioni sui tipi di team DevOps e aggiornamenti continui su DevOps in Atlassian.

Le persone collaborano utilizzando una parete piena di strumenti

Blog di Bitbucket

Illustrazione su Devops

Percorso di apprendimento DevOps

Funzione Demo Den per demo con esperti Atlassian

Come Bitbucket Cloud funziona con Atlassian Open DevOps

Iscriviti alla nostra newsletter DevOps

Thank you for signing up