Git squash e la contrazione di più commit
Oggi mi sono accorto che il lastBuildDate del mio feed
RSS non veniva aggiornato ogni volta che ce n’era
bisogno. Ho sistemato la cosa e, già che c’ero, ho messo mano ad alcune piccole
migliorie sparse nel codice del file rss.xml. Siccome il sito è sotto
controllo Git e avevo fatto diversi commit su più o meno lo stesso argomento,
volevo semplicemente riunirli in modo da avere una storia più pulita. In questi
casi, Git offre la possibilità di fare lo squash dei commit, cioè comprimerli
in uno solo, così da mantenere appunto una cronologia più ordinata e leggibile.
Questa pratica è particolarmente utile quando si lavora in gruppo o
semplicemente perché si vogliono evitare più commit tutti incentrati su un unico
aspetto. Contrariamente a quanto ci si potrebbe aspettare, però, non esiste un
comando diretto git squash, ma l’operazione si esegue attraverso il comando
interattivo git rebase -i. Non è complicato, ma è abbastanza tecnico da
meritare qualche appunto pratico, che annoto qui sia per me sia per chi volesse
provarci.
Nel mio repository avevo questi commit e volevo unificare gli ultimi 5, qui evidenziati in rosso in figura 1:

Figura 1. I commit da contrarre.
Da terminale ho eseguito:
$ git rebase -i HEAD~5
Git mi ha mostrato l’editor di testo con gli ultimi 5 commit, uno per riga, e
all’inizio di ogni riga la parola pick, come si vede in figura 2:

Figura 2. L’editor con i commit da modificare. L’ordine è inverso rispetto al log tradizionale di Git o a come mostrato in figura 1.
A questo punto bisogna dire a Git quali commit comprimere. Basta lasciare pick
sul primo commit in cima (il più vecchio tra i 5) e sostituire pick con
squash o s sugli altri, come in figura 3:

Figura 3. I commit da comprimere, con s al posto di pick.
Salviamo e chiudiamo. Si aprirà una nuova schermata dell’editor con tutti i messaggi dei commit coinvolti, così da poterli mantenere, modificare o cancellare:

Figura 4. I messaggi originali dei commit.
Nel mio caso, ho scritto un messaggio breve riassuntivo come oggetto del commit e, sotto, un elenco dettagliato delle modifiche, come mostrato in figura 5:

Figura 5. Il messaggio finale del commit unificato. Una riga vuota separa l’oggetto del commit dal resto del messaggio.
Dopo aver salvato, Git ha eseguito il rebase. Se ora controlliamo la cronologia dei commit, vedremo che i 5 sono stati unificati:

Figura 6. I 5 commit ora risultano fusi in uno solo.
La stessa situazione da terminale:
$ git log
commit 175a196eb64d0af98957dc813b5072169c177e4f (HEAD -> master)
Author: Aldo Latino <email@tld.com>
Date: Sun May 11 06:59:49 2025 +0200
Corretta data lastBuildDate in feed RSS, migliorie varie
- Fix lastBuildDate in feed RSS
- Changed Date to PublishDate in RSS pubDate
- Changed RSS content escaping, removed attribution
- Removed trailing dashes in RSS source
- Added leading dashes
commit 1f45056753e6bf8bb9f65b3bfbc96e9f17a75ef9
Author: Aldo Latino <email@tld.com>
Date: Sun May 11 06:08:51 2025 +0200
Aggiornato un link
commit 9a32ad1c8cc08dc1103410cc686b397de4416157 (origin/master, origin/HEAD)
Author: Aldo Latino <email@tld.com>
Date: Sat May 10 18:12:34 2025 +0200
Abilitato feed RSS solo in home
[...]
Lo squash dei commit è un ottimo modo per tenere ordinata la cronologia di un progetto. Dopo questa operazione, il repository risulta più leggibile e ordinato, specialmente quando si lavora in gruppo o si prepara una pull request. Un comando di Git che può tornare senza dubbio utile, anche se si lavora a un progetto del tutto personale.