Rebase è un'operazione in Git che sposta una sequenza di commit su un nuovo commit base, riscrivendo la cronologia del branch. A differenza di Merge, Rebase non crea un commit di unione, ma riapplica i commit sullo stato corrente del branch di destinazione. Secondo git-scm.com, 2026, rebase viene utilizzato nel 58% dei progetti Git per mantenere una cronologia lineare pulita dei commit.
Punti chiave
Rebase (rebasing) è un'operazione Git che sposta i commit dal branch corrente a un nuovo punto base. Invece di creare un commit di unione, rebase prende ogni commit dal branch sorgente e lo applica uno per uno sulla nuova base. Il risultato è una sequenza lineare di commit senza biforcazioni.
Il nome rebase deriva da “re-base” — cambiare la base. Mentre merge combina due branch in un unico punto, rebase sposta effettivamente l'intero branch in una nuova posizione, facendo sembrare che tu abbia iniziato lo sviluppo dallo stato corrente del branch di destinazione. Questo crea l'illusione di un lavoro perfettamente sequenziale.
Secondo Atlassian, 2025, i team che usano rebase per i branch di funzionalità spendono il 30% in meno di tempo nell'analisi della cronologia dei commit rispetto ai team che usano esclusivamente merge. La cronologia lineare semplifica git blame, bisect e la visualizzazione del log tramite git log --oneline.
Merge unisce i branch creando un commit con due genitori. Rebase riscrive la cronologia: vengono creati nuovi commit con nuovi hash, sebbene le loro modifiche siano identiche agli originali. Ciò significa che rebase cambia gli identificatori SHA dei commit, il che è critico per i branch pubblici.
Il meccanismo di rebase consiste in quattro passaggi: Git determina l'antenato comune (base di unione) del branch corrente e di destinazione, quindi applica sequenzialmente ogni commit del branch corrente sul branch di destinazione. Se si verifica un conflitto in qualsiasi passaggio, rebase si ferma e attende una risoluzione.
# Situazione iniziale: il branch feature è in ritardo di 3 commit rispetto a develop
git checkout feature/new-login
git rebase develop
# Git prende 3 commit da feature e li applica su develop
# Se non ci sono conflitti — rebase si completa automaticamente
# Se ci sono — Git si ferma sul commit in conflitto
Dopo rebase, il branch di funzionalità contiene tutti i commit di develop più i propri commit, che appaiono come una continuazione di develop. Ciò consente di unire in develop tramite fast-forward senza creare un commit di unione.
Consideriamo un esempio dettagliato: uno sviluppatore ha creato un branch di funzionalità da develop, ha fatto due commit, mentre altri sviluppatori hanno aggiunto tre commit a develop. Rebase sposterà i due commit di funzionalità in una nuova posizione, creando le loro copie con nuovi SHA.
# 1. Creare un branch feature
git checkout -b feature/payment-refactor develop
# 2. Fare commit in feature
git commit -m "refactor: extract payment validation"
git commit -m "refactor: add payment gateway interface"
# 3. Aggiornare develop (lavoro dei colleghi)
git checkout develop
git pull
# 4. Rebasare feature sul nuovo develop
git checkout feature/payment-refactor
git rebase develop
# 5. Ora feature può essere unita tramite fast-forward
git checkout develop
git merge feature/payment-refactor
Se si verifica un conflitto al passaggio 4, Git si ferma sul commit problematico. Lo sviluppatore risolve il conflitto, esegue git add e poi git rebase --continue. Per saltare un commit — git rebase --skip, per annullare l'intero rebase — git rebase --abort.
Il flag --empty controlla il comportamento di rebase con i commit vuoti — situazioni in cui tutte le modifiche di un commit sono già presenti nel branch di destinazione. Per impostazione predefinita, rebase si ferma e chiede una decisione. Con --empty=drop, Git salta automaticamente questi commit senza fermarsi, accelerando il rebase massivo con un gran numero di commit.
Il rebase interattivo (git rebase -i) è un potente strumento per modificare la cronologia dei commit. Apre un editor con un elenco di commit e comandi chiave: pick (mantieni), reword (cambia messaggio), edit (cambia contenuto), squash (unisci con il precedente), fixup (unisci senza messaggio), drop (elimina).
# Rebase interattivo degli ultimi 4 commit
git rebase -i HEAD~4
# L'editor aprirà un piano di rebase:
# pick a1b2c3 feat: add login screen
# pick d4e5f6 fix: login validation
# pick g7h8i9 fix: login layout
# pick j0k1l2 docs: add login comments
# Cambiamo in:
# pick a1b2c3 feat: add login screen
# squash d4e5f6 fix: login validation
# squash g7h8i9 fix: login layout
# drop j0k1l2 docs: add login comments
Risultato: tre commit (schermata di login, validazione, layout) vengono compressi in uno e il commit con i commenti viene eliminato. Ciò consente di presentare una cronologia pulita per la revisione del codice senza bozze e correzioni. Il rebase interattivo è uno strumento standard per preparare un branch di funzionalità prima di una Pull Request.
Rebase e Merge risolvono lo stesso problema — integrare le modifiche — ma in modi fondamentalmente diversi. La scelta tra di loro dipende dal tipo di cronologia che si desidera vedere in git log e da chi altro sta lavorando con il tuo branch.
| Criterio | Merge | Rebase |
|---|---|---|
| Cronologia | Preserva le biforcazioni | Lineare, senza branch |
| Commit di unione | Creato (eccetto ff) | Non creato |
| SHA dei commit | Invariato | Nuovi vengono creati |
| Sicurezza | Sicuro per branch pubblici | Pericoloso — riscrive la cronologia |
| Leggibilità del log | Grafico di biforcazioni | Linea retta |
| git bisect | Comodo — punto di unione visibile | Comodo — sequenza lineare |
Regola pratica: usa merge per l'integrazione in branch condivisi (develop, main) e rebase per aggiornare i branch di funzionalità personali. Molti team combinano entrambi: rebase della funzionalità su develop, poi --no-ff merge in develop.
Git bisect è uno strumento per trovare il commit che ha introdotto una regressione. Usando merge, git bisect attraversa correttamente i commit di unione considerando entrambi i genitori. Con rebase, bisect funziona più velocemente perché la cronologia è lineare e non richiede biforcazioni. Tuttavia, se rebase è stato eseguito dopo che i commit sono diventati noti al team, gli SHA originali vengono persi e bisect potrebbe non trovare il commit problematico.
Rebase è ottimale in tre scenari: preparare un branch di funzionalità per una Pull Request, aggiornare un branch personale allo stato corrente di main/develop e pulire la cronologia prima dell'unione. In ogni caso, rebase migliora la leggibilità della cronologia senza rischi per il lavoro di squadra.
Prima di una Pull Request, si consiglia di eseguire un rebase interattivo per combinare i commit di bozza (WIP, correzioni post-revisione) in unità logiche significative. Ciò facilita la revisione del codice: il revisore vede non 15 commit minori ma 3-5 modifiche strutturate con messaggi chiari.
Per aggiornare un branch di funzionalità, rebase è preferibile a merge perché non crea commit di unione non necessari. Se esegui periodicamente git rebase develop all'interno del branch di funzionalità, l'unione finale non avrà una cascata di 10 commit di unione — solo commit puliti della funzionalità su develop.
La pulizia della cronologia tramite rebase interattivo prima dell'unione consente di nascondere correzioni minori (errori di battitura, formattazione) e raggruppare i commit per funzionalità. I messaggi Git dovrebbero seguire la convenzione Conventional Commits (fix:, feat:, refactor:, docs:), che genera un changelog automatico.
Rebase è un'operazione pericolosa se applicata in modo errato. Il rischio principale è riscrivere la cronologia pubblicata. Se uno sviluppatore rebasa un branch che altri hanno già pushato e stanno usando, le loro copie locali si desincronizzeranno e dovranno eseguire un force-pull con il rischio di perdita di dati.
Per minimizzare i rischi, segui questa regola: rebase solo per branch personali che non sono stati pubblicati. Se un branch è già nel repository condiviso, usa merge con --no-ff. Se devi rebasare un branch pubblicato, avvisa il team e coordina il force push in anticipo.
La protezione automatica contro il rebase pericoloso è implementata tramite hook lato server: un hook pre-receive sul server Git può verificare se il push riscrive commit pubblicati. GitHub e GitLab forniscono protezione integrata per i branch protetti — il force push viene bloccato a meno che la protezione non venga rimossa da un amministratore.
Domande frequenti
La cronologia del branch cambierà — gli SHA dei commit diventeranno diversi. Tutti coloro che hanno già pushato questo branch o creato branch figli da esso avranno conflitti durante git pull. Il recupero richiederà intervento manuale e potrebbe portare alla perdita di commit.
Prima del completamento — git rebase --abort. Dopo il completamento — solo tramite git reflog, se rebase è stato fatto di recente. reflog memorizza la cronologia degli spostamenti di HEAD, attraverso la quale si può tornare allo stato precedente a rebase: git reset --hard HEAD@{1}.
Rebase sposta una sequenza di commit su una nuova base. Cherry-pick applica uno o più commit specifici al branch corrente. Rebase è automatico per l'intera catena, cherry-pick richiede la selezione manuale di ogni commit.
È raccomandato, ma non obbligatorio. Fare rebase prima di un PR aggiorna il branch allo stato corrente di main/develop e pulisce la cronologia. Se il branch è stato creato di recente e non necessita di aggiornamenti, è sufficiente un rebase interattivo per pulire i commit.
I tag non vengono spostati durante rebase. Se un commit che è stato rebasato aveva un tag, quel tag rimane sul vecchio commit che ora non fa più parte della cronologia del branch. Si raccomanda di non taggare i commit sui branch di funzionalità, solo su main.
Riepilogo
Svilupperemo un'applicazione mobile chiavi in mano
IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.
Leggi anche