W3docs

git rebase -i (interattivo)

Impara il rebase interattivo con git rebase -i per unire, rinominare, modificare, eliminare e riordinare i commit prima di condividerli.

Cos'è il rebase interattivo

Il rebase interattivo, avviato con git rebase -i, consente di riscrivere una serie di commit prima di condividerli. Apre una "lista todo" modificabile dei commit in cui decidi, riga per riga, cosa fare con ciascuno — tenerlo, rinominare il messaggio, unirlo a un altro, dividerlo, riordinarlo oppure eliminarlo. Si basa sul classico git rebase ma ti mette in controllo di ogni singolo passaggio.

Questa pagina spiega come avviare un rebase interattivo, tutti i comandi disponibili nella lista todo, i flussi di lavoro più comuni (unire commit, rinominare messaggi, riordinare, eliminare e dividere commit), come recuperare la situazione quando qualcosa va storto e l'unica regola che lo rende sicuro.

Una lista todo di rebase interattivo che unisce e rinomina commit

Un commit è uno snapshot salvato del tuo lavoro; HEAD è un puntatore al commit su cui ti trovi attualmente. "Riscrivere la storia" significa produrre nuovi commit per sostituire quelli esistenti — Git non modifica mai un commit sul posto, quindi ogni commit riscritto ottiene un hash completamente nuovo.

Avviare un rebase interattivo

Punta il comando al commit precedente al primo che vuoi modificare — il rebase riprodurrà tutto ciò che viene dopo. Per rivedere gli ultimi tre commit:

git rebase -i HEAD~3

HEAD~3 significa "tre commit indietro da HEAD". Puoi anche indicare un commit esplicito (git rebase -i a1b2c3d) oppure, su un branch, fare il rebase di tutto ciò che è divergito da un altro branch (git rebase -i main).

Git apre il tuo editor configurato con una riga per commit, il più vecchio in cima (l'opposto di git log):

pick a1b2c3d add login form
pick b2c3d4e fix typo
pick c3d4e5f more css tweaks

Sotto la lista, Git include un cheat sheet commentato di tutti i comandi disponibili. Cambi la parola all'inizio di ogni riga per scegliere un'azione, eventualmente riordini le righe, quindi salvi e chiudi. Git riproduce i commit dall'alto verso il basso seguendo le tue istruzioni. Se salvi il file invariato (o elimini ogni riga), il rebase non fa nulla e si ferma.

I comandi della lista todo

Ogni riga inizia con un comando. Questi sono quelli che usi più spesso:

ComandoBreveEffetto
pickpUsa il commit così com'è.
rewordrUsa il commit ma modifica il suo messaggio.
editeMette in pausa sul commit così puoi modificarne il contenuto (amend, dividere o aggiungere file).
squashsCombina nel commit precedente, unendo entrambi i messaggi.
fixupfCome squash, ma scarta il messaggio di questo commit.
dropdRimuove completamente il commit (eliminare la riga fa lo stesso).
execxEsegue un comando shell (ad es. test) in quel punto del rebase.

Non esiste un comando reorder — riordini i commit semplicemente spostando le righe in su o in giù nella lista todo. Le righe vengono applicate dall'alto verso il basso, quindi l'ordine che lasci è l'ordine con cui Git crea i commit.

Unire commit insieme

Una pulizia comune è quella di raggruppare diversi piccoli commit in uno solo. Segna il primo come pick e il resto come squash (oppure fixup per scartare i loro messaggi):

pick a1b2c3d add login form
squash b2c3d4e fix typo
fixup c3d4e5f more css tweaks

squash/fixup uniscono sempre verso l'alto, nella riga precedente. Quando salvi, Git combina i tre in un unico commit. Poiché b2c3d4e è stato sottoposto a squash, Git apre un secondo editor che mostra entrambi i messaggi dei commit così puoi scrivere un messaggio pulito; il fixup di c3d4e5f contribuisce con le sue modifiche ma scarta silenziosamente il suo messaggio.

Se vuoi semplicemente incorporare piccoli commit "oops" in uno precedente, dai un'occhiata a git commit --fixup (vedi git commit --amend e git rebase -i --autosquash), che contrassegna le righe automaticamente.

Rinominare il messaggio di un commit

Per correggere un errore di battitura o chiarire un messaggio senza toccare il codice, contrassegna la riga con reword:

pick a1b2c3d add login form
reword b2c3d4e fix tpyo
pick c3d4e5f more css tweaks

Git riproduce a1b2c3d così com'è, poi si ferma e apre un editor con il vecchio messaggio di b2c3d4e così puoi riscriverlo, poi continua. Le modifiche del commit rimangono intatte — cambia solo il messaggio (e il suo hash).

Riordinare ed eliminare commit

Per cambiare l'ordine, sposta le righe. Per eliminare un commit, contrassegnalo con drop o elimina la riga. Questa lista todo riordina la modifica CSS prima della correzione del typo ed elimina completamente il commit del typo:

pick a1b2c3d add login form
pick c3d4e5f more css tweaks
drop b2c3d4e fix typo

Eliminare o riordinare può causare conflitti se un commit successivo dipendeva da quello rimosso o spostato — Git si fermerà e ti lascerà risolverli.

Dividere un commit

Per suddividere un commit grande in più parti, contrassegnalo con edit. Git si ferma su quel commit con le modifiche già applicate; poi annulli il commit mantenendo le modifiche e ricrei commit più piccoli:

# rebase pauses on the commit marked 'edit'
git reset HEAD~          # move the commit's changes back to the working tree
git add login.js
git commit -m "add login form markup"
git add styles.css
git commit -m "style the login form"
git rebase --continue    # resume the rest of the rebase

git reset HEAD~ annulla l'ultimo commit ma lascia le sue modifiche nei file (vedi git reset), così puoi preparare e committare le modifiche in commit più piccoli e separati.

Completare o annullare

Se un passaggio causa un conflitto, Git si ferma così puoi risolverlo. Modifica i file in conflitto, prepara le correzioni con git add, poi continua:

git rebase --continue

Se decidi che un determinato commit non debba essere applicato affatto mentre sei fermo su un conflitto, usa git rebase --skip. Per abbandonare l'intero rebase e tornare esattamente al punto di partenza:

git rebase --abort

Anche dopo che un rebase è completato, i commit originali non vengono persi immediatamente — rimangono raggiungibili attraverso git reflog per un certo periodo, che è la rete di sicurezza se fai un rebase e te ne penti.

Una parola di cautela

Il rebase interattivo riscrive la storia — i commit risultanti hanno nuovi hash. È perfetto per riordinare il tuo branch prima di aprire una pull request, ma non fare mai il rebase di commit che altri hanno già scaricato. Riscrivere la storia condivisa costringe tutti gli altri a riconciliare copie divergenti, e per effettuare il push del risultato è richiesto un force push (git push --force-with-lease). La regola d'oro: rebase in locale, merge in pubblico.

Se devi cambiare solo l'ultimo commit, di solito non hai bisogno di un rebase completo — git commit --amend è più semplice. Per copiare un singolo commit da altrove nel tuo branch, vedi git cherry-pick.

Una guida completa allo squash

Ecco una sequenza completa che puoi eseguire in una cartella vuota per vedere lo squash in azione. Crea quattro commit, poi unisce gli ultimi tre in uno:

git init -b main demo && cd demo
git config user.email [email protected]
git config user.name You

echo "init"  > base && git add base && git commit -m "initial commit"
echo "a"     > f    && git add f    && git commit -m "add login form"
echo -e "a\nb" > f  && git add f    && git commit -m "fix typo"
echo -e "a\nb\nc" > f && git add f  && git commit -m "more css tweaks"

git log --oneline      # four commits
git rebase -i HEAD~3   # mark line 2 'squash', line 3 'fixup', save
git log --oneline      # now: "initial commit" + one combined commit

Dopo il rebase, git log --oneline mostra solo due commit — il commit iniziale e un unico commit combinato — e il file f contiene ancora tutte e tre le righe (a, b, c). Il lavoro è identico; è solo la storia dei commit ad essere più ordinata.

Esercitazione

Pratica
Quali affermazioni sul rebase interattivo sono corrette?
Quali affermazioni sul rebase interattivo sono corrette?
Was this page helpful?