Interactive rebase è talvolta chiamato il “coltellino svizzero” di Git – perché contiene così tanti strumenti diversi, per così tanti casi d’uso diversi! Tuttavia, c’è un caso d’uso principale: ripulire la tua storia di commit locale.
Ricorda la parola “locale”: dovrebbe essere usato solo per ripulire la tua storia di commit locale, per esempio prima di integrare uno dei tuoi rami di feature in un ramo del team. Al contrario, NON dovrebbe essere usato sulla cronologia dei commit che è già stata spinta e condivisa su un repository remoto. Interactive rebase è uno di quegli strumenti che “riscrivono” la storia di Git – e non dovresti farlo su commit che sono già stati condivisi con altri.
Con questo piccolo messaggio di avvertimento fuori dai piedi, guardiamo alcuni esempi pratici!
Nota: per una più facile visualizzazione degli scenari e dei flussi di lavoro in questo post, ho usato la GUI desktop di Git “Tower” in alcuni dei miei screenshot.
Correzione di un vecchio messaggio di commit
A volte si nota un refuso in un vecchio messaggio di commit – o si è dimenticato di menzionare qualcosa nella descrizione che è degno di nota. Se stessimo parlando dell’ultimo commit, avremmo potuto semplicemente usare l’opzione --amend
del comando git commit
. Ma per i commit più vecchi dovrai usare il rebase interattivo per cambiarli dopo il fatto.
Ecco un esempio di un messaggio di commit andato terribilmente male che vogliamo correggere:
Un cattivo messaggio di commit che necessita di correzione
Il primo passo in qualsiasi sessione di rebase interattivo è determinare quale parte della storia dei commit vuoi manipolare. Per riprendere l’esempio precedente: per cambiare questo cattivo commit dobbiamo iniziare la sessione dal suo commit padre.
Avviare la nostra sessione di rebase interattivo
Possiamo ora inserire l’hash di questo commit di partenza nel comando di rebase interattivo:
$ git rebase -i 0023cddd
Si aprirà una finestra di editor, contenente una lista dei commit che avete appena selezionato per la manipolazione. E non sorprenderti perché sono in ordine inverso: in una sessione interattiva di rebase, Git riapplicherà i vecchi commit, elemento dopo elemento – il che significa che invertire l’ordine è corretto dal punto di vista di Git.
Finestra dell’editor con i commit selezionati
Un’altra cosa importante da notare su questa finestra dell’editor: qui non si eseguono le manipolazioni effettive! O, in questo esempio concreto, NON vai avanti e cambi il messaggio di commit qui. Invece, segnate solo il commit che volete cambiare con una parola chiave di azione. Nel nostro caso, poiché vogliamo cambiare il messaggio di un commit, contrassegniamo la linea con “reword”. Se poi salvi e chiudi questa finestra dell’editor, se ne aprirà una nuova, contenente il vecchio messaggio del commit. Ora è il momento di fare finalmente le tue modifiche:
Finalmente, possiamo fare le nostre modifiche
Dopo aver salvato e chiuso ancora una volta, la sessione di rebase interattivo è completa e il nostro vecchio messaggio di commit è stato corretto!
Combinare più commit in uno
Un altro caso di utilizzo del rebase interattivo è quando si vogliono combinare più vecchi commenti in uno. Anche se, naturalmente, si applica la regola d’oro del controllo di versione: nella maggior parte delle situazioni, è vantaggioso creare più e più piccoli commit invece di pochi e grandi. Tuttavia, come per ogni cosa, potremmo scoprire che abbiamo esagerato e ora vogliamo fondere due o più vecchi commit in uno solo.
Per fare un esempio concreto, diciamo che vogliamo combinare i seguenti commit selezionati in uno solo:
Combiniamo più commit in uno
Proprio come nel nostro primo caso, iniziamo iniziando la sessione interattiva di rebase almeno al commit padre di quello che vogliamo manipolare.
$ git rebase -i 2b504bee
Di nuovo, si aprirà una finestra dell’editor che elencherà la parte della storia del nostro commit che vogliamo manipolare:
Marcare le linee con “squash”
La parola chiave di azione che stiamo per usare qui si chiama “squash”. E c’è solo un’informazione importante che devi sapere su squash per poterla usare: la linea che contrassegniamo con la parola chiave “squash” sarà combinata con la linea direttamente sopra. Ecco perché, come potete vedere nel mio screenshot qui sopra, ho segnato la linea #2 con “squash” per combinarla con la linea #1.
Possiamo ora salvare e chiudere la finestra dell’editor e di nuovo guardare e una nuova finestra appare: ci viene ora chiesto di fornire un messaggio di commit per il nuovo commit che viene creato quando si combinano quei due vecchi.
Inserimento di un nuovo messaggio per il nuovo commit schiacciato
Dopo aver salvato e chiuso questa finestra dell’editor, si vedrà che è stato creato un nuovo commit che contiene i changeset di entrambi i vecchi commit. Voilà!
Fissare un errore
Un altro caso d’uso per il rebase interattivo è quando hai trovato un errore in uno dei tuoi commit precedenti. E non importa cosa esattamente avete sbagliato: potreste aver dimenticato di aggiungere un certo cambiamento, avreste dovuto cancellare un file, o semplicemente introdurre un refuso…
La tendenza naturale, in una tale situazione, è di creare semplicemente un nuovo commit che corregga l’errore. Ma d’altra parte, questo incasinerà la nostra storia dei commit: fare un commit originale, e poi aggiungere un commit “cerotto” solo per correggere qualche errore… è un modo disordinato di lavorare. La vostra cronologia dei commit diventerà presto difficile da capire, perché è disseminata di tutti quei piccoli “quick fix commits”!
E’ qui che “fixup”, uno degli strumenti forniti con interactive rebase, diventa molto utile. Fixup prende questo commit “quick fix”, applica le sue modifiche al commit originale (correggendolo così), e poi si libera del commit cerotto:
Come funziona “fixup”
Dopo che abbiamo finito, sembra come se non ci fosse mai stato un problema con il nostro commit originale! Quindi facciamo un esempio pratico.
Il primo passo è fare tutto ciò che è necessario per correggere il problema: questo potrebbe significare aggiungere un nuovo file, fare modifiche a quelli esistenti, cancellare file obsoleti… è necessario “solo” produrre le modifiche che correggono l’errore.
Il passo successivo è quello di fare il commit di queste modifiche al repository – ma con un piccolo extra: quando facciamo il commit, useremo il flag --fixup
e diremo a Git l’hash del nostro cattivo commit:
$ git add corrections.txt$ git commit --fixup 2b504bee
Se ora dai un’occhiata alla cronologia dei commit, vedrai che è stato creato un commit dall’aspetto piuttosto ordinario – probabilmente non la magia e i fuochi d’artificio che ti saresti aspettato. Ma se date un’occhiata più da vicino, vedrete che sta succedendo qualcosa: il nuovo commit è stato automaticamente anteposto a “fixup !” e all’oggetto del nostro cattivo commit.
Il commit originale e il fix commit
Il terzo passo ora è iniziare la sessione interattiva di rebase. Ancora una volta, scegliamo il genitore del nostro cattivo commit come punto di partenza…
$ git rebase -i 0023cddd --autosquash
… e come seconda parte della salsa segreta, stiamo usando il flag --autosquash
. Questa opzione fa sì che non dobbiamo fare nulla nella finestra dell’editor che è ora aperta. Date un’occhiata da vicino alla situazione:
Il nostro commit di correzione è segnato “fixup” e ordinato nella giusta posizione
Vedrete che Git ha fatto automaticamente due cose per noi:
- Ha segnato il nostro commit di fascia come “fixup.”
- Ha riordinato le linee in modo che il nostro commit per il band-aid appaia direttamente sotto il nostro commit cattivo. Questo perché fixup funziona esattamente come squash nel senso che si combina con la linea precedente.
In altre parole: non c’è più niente da fare per noi se non salvare e chiudere la finestra dell’editor.
Diamo un’altra occhiata alla storia del commit:
Un lieto fine!
Non solo il nostro commit originariamente cattivo ora contiene le modifiche del nostro commit band-aid. Ma soprattutto, il brutto commit “band-aid” è scomparso dalla cronologia dei commit! Tutto è bello e pulito, proprio come se non ci fosse mai stato un problema!
Scopri il potere del rebase interattivo
Ci sono molti casi d’uso per il rebase interattivo – e la maggior parte di essi nel reparto “correzione degli errori”. Per una panoramica di altre cose utili che puoi fare, ti consiglio il gratuito “First Aid Kit for Git”: è una raccolta di brevi video (2-3 min per episodio) che ti aiutano a imparare a riparare gli errori usando interactive rebase e altri strumenti Git.
Nota del redattore: ho dovuto usare interactive rebase durante la revisione di questo stesso post! Uno dei miei commit includeva un’immagine che era maggiore di 1MB che è contro le regole per il progetto del sito web GitLab. Sono dovuto tornare indietro e correggere quel commit per includere invece un’immagine di dimensioni corrette. Grazie per la lezione, universo! 😁
Altri consigli e trucchi Git
- 15 consigli Git per migliorare il tuo flusso di lavoro
- Come Git Partial Clone ti permette di recuperare solo il file grande di cui hai bisogno
- Git succede! 6 errori comuni di Git e come risolverli
A proposito dell’autore ospite
Tobias Günther è il CEO di Tower, il popolare client desktop Git che aiuta più di 100.000 sviluppatori in tutto il mondo ad essere più produttivi con Git.
Immagine di copertina di David Taljat su Pexels