Salta al contenuto principale

03 - Git Rebase vs Merge: Quando Usare Cosa

Confronto dettagliato tra git rebase e merge: differenze, vantaggi, svantaggi, fast-forward e quando usare ciascuna strategia per una storia Git ottimale.

Cosa ne pensi di questo articolo?

In Breve

Confronto dettagliato tra git rebase e merge: differenze, vantaggi, svantaggi, fast-forward e quando usare ciascuna strategia per una storia Git ottimale.

Git Rebase vs Merge: Quando Usare Cosa

Una delle decisioni più discusse in Git è: usare rebase o merge? Entrambi integrano cambiamenti da un branch all'altro, ma in modi radicalmente diversi. Capire le differenze, i vantaggi e gli svantaggi di ciascuno è essenziale per mantenere una storia Git pulita e collaborare efficacemente in team.

🎯 Cosa Imparerai

  • Differenze fondamentali tra rebase e merge
  • Quando usare rebase e quando merge
  • Fast-forward merge vs merge commit
  • La regola d'oro del rebase

Come Funziona il Merge

Git merge crea un nuovo merge commit che unisce le storie di due branch. È un'operazione non distruttiva: i branch originali non vengono modificati.

Merge Base
# Situazione iniziale
main:    A---B---C
              \
feature:       D---E

# Merge di feature in main
git checkout main
git merge feature

# Risultato
main:    A---B---C-------M
              \         /
feature:       D---E---

# M è il merge commit che ha due genitori: C ed E
Eseguire un Merge
# Passa al branch di destinazione
git checkout main

# Mergia il feature branch
git merge feature

# Git crea automaticamente un merge commit
# Messaggio default: "Merge branch 'feature' into main"

Come Funziona il Rebase

Git rebase riscrive la storia spostando i commit di un branch su una nuova base. Invece di creare un merge commit, i commit vengono riapplicati uno per uno sulla punta del branch di destinazione.

Rebase Base
# Situazione iniziale
main:    A---B---C
              \
feature:       D---E

# Rebase di feature su main
git checkout feature
git rebase main

# Risultato
main:    A---B---C
                  \
feature:           D'---E'

# D' ed E' sono NUOVI commit con contenuto uguale a D ed E
# ma hash diversi (perché il parent è cambiato)
Eseguire un Rebase
# Passa al feature branch
git checkout feature

# Rebase su main
git rebase main

# I commit di feature vengono riapplicati su main
# Se ci sono conflitti, risolvili e:
git add .
git rebase --continue

# Ora puoi fare fast-forward merge su main
git checkout main
git merge feature  # Fast-forward (nessun merge commit)

Fast-Forward Merge

Un fast-forward merge accade quando il branch di destinazione non ha commit nuovi rispetto al branch da mergeare. Git semplicemente "sposta avanti" il puntatore senza creare merge commit.

Fast-Forward
# Situazione dopo rebase
main:    A---B---C
                  \
feature:           D'---E'

# Fast-forward merge
git checkout main
git merge feature

# Risultato (nessun merge commit)
main:    A---B---C---D'---E'
                          |
feature:                  

Per evitare fast-forward e forzare un merge commit:

git merge --no-ff feature

Differenze Chiave

Merge:

  • Storia ramificata: Mostra quando i branch hanno diverged
  • Non distruttivo: Storia originale preservata
  • Tracciabile: Vedi esattamente quando è avvenuto il merge
  • Sicuro: Nessuna riscrittura della storia
  • Crea merge commit aggiuntivi

Rebase:

  • Storia lineare: Come se avessi lavorato sequenzialmente
  • Distruttivo: Riscrive commit (nuovi hash)
  • Pulito: Nessun merge commit rumoroso
  • Rischioso: Mai fare rebase di branch pubblici!
  • Storia più facile da leggere

Quando Usare Merge

✅ Usa Merge quando:

  • Integri branch pubblici (main, develop)
  • Vuoi preservare la storia esatta di quando i branch hanno diverged
  • Lavori in team e altri hanno già pullato il branch
  • Vuoi tracciare milestone (feature completate, release)
  • Segui Git Flow (usa --no-ff per preservare struttura)
Esempio: Merge in Team
# Feature branch completato
git checkout main
git merge --no-ff feature/user-auth

# Merge commit preserva la storia della feature
# Chiaro quando la feature è stata integrata
# Altri sviluppatori vedono la struttura completa

Quando Usare Rebase

✅ Usa Rebase quando:

  • Lavori su branch locali privati
  • Vuoi storia lineare pulita
  • Stai aggiornando il tuo feature branch con gli ultimi cambiamenti da main
  • Vuoi evitare merge commit "rumorosi"
  • Prima di creare una Pull Request (per storia pulita)
Esempio: Mantenere Feature Branch Aggiornato
# Il tuo feature branch è indietro rispetto a main
git checkout feature/payment
git rebase main

# Ora il tuo branch ha gli ultimi cambiamenti da main
# Storia lineare, facile da revieware nella PR

# Risolvi conflitti se necessario
# git add .
# git rebase --continue

La Regola d'Oro del Rebase

⚠️ REGOLA D'ORO

Mai fare rebase di commit che sono stati pushati su branch pubblici condivisi!

Il rebase riscrive la storia cambiando gli hash dei commit. Se altri sviluppatori hanno già basato il loro lavoro su quei commit, il loro repository diventa inconsistente e il prossimo pull causerà conflitti e duplicazioni.

❌ Cattivo: Rebase di Branch Pubblico
# MALE! Altri hanno già pullato main
git checkout main
git rebase feature

# Questo riscrive main, causando problemi per tutti
✅ Buono: Rebase di Branch Privato
# BENE! feature è solo tuo, nessuno l'ha pullato
git checkout feature
git rebase main

# Aggiorna il tuo branch privato con gli ultimi cambiamenti

Workflow Consigliato

Ecco un workflow che combina il meglio di entrambi:

Workflow Ibrido Merge + Rebase
# 1. Crea feature branch da main
git checkout -b feature/new-feature main

# 2. Lavora sulla feature
git commit -m "feat: add component"
git commit -m "feat: add tests"

# 3. Nel frattempo, main è andato avanti
# Aggiorna il tuo branch con rebase (branch privato, OK!)
git fetch origin
git rebase origin/main

# 4. Pulizia della storia con interactive rebase (opzionale)
git rebase -i origin/main
# Squash commit WIP, fixup typos, ecc.

# 5. Push del feature branch
git push origin feature/new-feature

# 6. Crea Pull Request su GitHub/GitLab

# 7. Dopo code review, mergia in main CON merge commit
git checkout main
git merge --no-ff feature/new-feature

# Risultato: storia main pulita con milestone chiare

Storia Lineare vs Ramificata

Storia con Merge:

*   Merge feature B
|\
| * Feature B commit 2
| * Feature B commit 1
* | Main commit 3
* | Main commit 2
|/
* Main commit 1

Pro: Vedi esattamente quando le feature sono state integrate

Con: Può diventare caotica con molti merge

Storia con Rebase:

* Feature B commit 2
* Feature B commit 1
* Main commit 3
* Main commit 2
* Main commit 1

Pro: Lineare, facile da seguire

Con: Perdi informazione su quando i branch hanno diverged

Conflitti: Merge vs Rebase

Entrambi possono avere conflitti, ma si gestiscono diversamente:

Risolvere Conflitti
# Conflitti durante MERGE
git merge feature
# Risolvi conflitti
git add .
git commit  # Completa il merge

# Conflitti durante REBASE
git rebase main
# Risolvi conflitti per ogni commit in conflitto
git add .
git rebase --continue  # Vai al prossimo commit
# Ripeti fino alla fine

# Abortire rebase se necessario
git rebase --abort

Preferenze di Team

Diversi team hanno preferenze diverse. Alcuni esempi:

  • Linux Kernel: Solo merge (preserva storia completa)
  • Rails: Rebase per feature branch, merge per integrazioni importanti
  • Google: Storia lineare con rebase (trunk-based development)

Conclusione

Non esiste una scelta "migliore" universale tra merge e rebase. Merge preserva la storia ed è sicuro per branch pubblici. Rebase crea storia lineare pulita ma riscrive commit. La strategia migliore è spesso ibrida: usa rebase per mantenere puliti i tuoi feature branch locali, e merge con --no-ff per integrare in branch pubblici.

🎯 Punti Chiave

  • Merge = non distruttivo, crea merge commit, storia ramificata
  • Rebase = riscrive storia, nessun merge commit, storia lineare
  • Mai fare rebase di branch pubblici condivisi
  • Usa rebase per feature branch privati, merge per integrazioni pubbliche
  • Fast-forward merge = nessun merge commit quando possibile

Domande frequenti

Come funziona il Git Merge?

Git merge crea un nuovo commit di fusione che unisce le storie di due rami.

Qual è la differenza tra un fast-forward merge e un normale merge?

Un fast-forward merge accade quando il ramo di destinazione non ha nuovi commit rispetto al ramo da fusionare, mentre un normale merge crea un nuovo commit di fusione.

Perché è importante evitare di fare rebase su commit che sono stati pushati su rami pubblici condivisi?

Il rebase riscrive la storia cambiando gli hash dei commit, il che può causare conflitti e duplicazioni se altri sviluppatori hanno già basato il loro lavoro su quei commit.

Qual è la strategia migliore per mantenere una storia Git pulita?

La strategia migliore è spesso ibrida: usare rebase per mantenere puliti i tuoi rami feature locali, e merge con per integrare in rami pubblici.

Fonti e approfondimenti

Prova Questi Strumenti

Strumenti gratuiti correlati a questo argomento.

Commenti

Caricamento commenti...

Accedi per commentare

Discuti questo articolo nella community

Unisciti al gruppo Telegram per discutere con altri sviluppatori, fare domande e condividere le tue esperienze.

Ti è piaciuto questo articolo?

Esplora altri contenuti sul blog o scopri i miei progetti