Git merge vs rebase: differenze, esempi e quando usare ciascuno

  1. Home
  2. Blog
  3. Sviluppo software
Sviluppo software

Git merge vs rebase: differenze, esempi e quando usare ciascuno

Git merge vs rebase decide come appare la cronologia del tuo progetto. Guarda entrambi sullo stesso esempio con output reale del log, impara la regola che evita i disastri e copia un flusso di lavoro sicuro per il team.

7 min di lettura
Git merge vs rebase: differenze, esempi e quando usare ciascuno
Punti chiave
  • Merge unisce due branch con un nuovo commit di merge e mantiene la cronologia esattamente com’è avvenuta.
  • Rebase riapplica i tuoi commit sopra un altro branch, ottenendo una linea retta ma nuovi hash.
  • Non fare mai il rebase di commit che altri hanno già scaricato.
  • Fai il rebase del tuo branch di funzionalità prima di aprire una pull request e usa il merge quando lo porti nel branch principale.

Il tuo branch di funzionalità è indietro rispetto a main e ti serve il lavoro nuovo. Git merge vs rebase è la scelta tra due modi per ottenerlo, ed entrambi sono corretti. Cambia l’aspetto della cronologia dopo.

Abbiamo creato un piccolo repository, eseguito entrambi i comandi e incollato l’output reale qui sotto, così confronti il risultato invece di immaginarlo. Sei nuovo con Git? Parti dal nostro tutorial Git per principianti (in inglese).

Cosa fanno git merge e git rebase

git merge prende le punte di due branch e le combina. Se entrambi hanno commit nuovi, Git crea un commit di merge con due genitori. Nulla di ciò che esiste viene modificato.

git rebase prende i commit presenti solo nel tuo branch, li mette da parte, sposta il branch sulla punta dell’altro e poi li riapplica uno alla volta. I commit riapplicati sono commit nuovi con hash nuovi, anche se le modifiche sono le stesse.

Git merge in pratica

Il nostro punto di partenza: commit A su main, due commit (F1, F2) su feature e un altro commit (M1) aggiunto dopo a main. Ora facciamo il merge di main in feature.

git switch feature
git merge main
git log --oneline --graph

*   f507aab Merge main into feature
|\
| * 8842fb5 M1
* | 082cc6a F2
* | 5a71e3c F1
|/
* 8766865 A

Il grafo mostra la storia reale: due linee di lavoro che sono state unite. I commit originali F1 e F2 mantengono i loro hash. Il costo è un commit di merge in più e, in un progetto attivo, il grafo diventa una ragnatela.

Git rebase in pratica

Stesso punto di partenza, ma questa volta facciamo il rebase di feature su main.

git switch feature
git rebase main
git log --oneline --graph

* 1ff474b F2
* bf9149e F1
* 8842fb5 M1
* 8766865 A

La cronologia è una linea retta, come se avessi iniziato dopo M1. Guarda gli hash: F1 era 5a71e3c e ora è bf9149e, mentre F2 è passato da 082cc6a a 1ff474b. Git li ha riscritti, ed è per questo che il rebase richiede attenzione.

Merge e rebase a confronto

AspettoMergeRebase
Forma della cronologiaGrafo ramificato con commit di mergeUna linea retta
Commit esistentiInvariatiRiscritti con nuovi hash
ConflittiRisolti una volta, nel commit di mergePossono servire correzioni per ogni commit riapplicato
Sicuro sui branch condivisiSìNo
Ideale perIntegrare in main il lavoro finitoAggiornare il proprio branch prima della revisione

Suggerimento: se non riesci a decidere, chiediti chi altro ha il tuo branch. Se nessuno, il rebase è sicuro. Se un collega lo ha scaricato, usa il merge.

La regola d’oro del rebase

Non fare il rebase di commit che esistono fuori dal tuo repository. Dopo un rebase il tuo branch non coincide più con la copia sul server, quindi per inviarlo serve un push forzato. Se un collega ha costruito lavoro sui vecchi commit, la sua cronologia ora diverge dalla tua e sistemarla è doloroso.

Fare il rebase del tuo branch di funzionalità privato va bene. Farlo su main o su qualsiasi branch usato da altri, no.

Un flusso di lavoro sicuro per il team

Questa routine mantiene pulita la cronologia senza sorprendere nessuno. È anche ciò che la maggior parte dei team usa prima della pipeline CI, come quella della nostra guida a GitHub Actions CI/CD (in inglese).

git switch feature
git fetch origin
git rebase origin/main        # or: git pull --rebase
# fix conflicts, then: git add <file> && git rebase --continue
git push --force-with-lease   # only on your own branch

--force-with-lease si rifiuta di sovrascrivere il branch sul server se qualcuno ha fatto push dopo il tuo ultimo fetch, cosa che un semplice --force distruggerebbe in silenzio. Quando la pull request è approvata, fai il merge in main.

Come annullare un rebase sbagliato

Un rebase sembra distruttivo, ma i vecchi commit restano per un po’ nel reflog di Git, quindi puoi tornare indietro.

git reflog                    # find the commit before the rebase
git reset --hard HEAD@{5}     # example position, check reflog first

Crea un branch di backup con git branch backup prima di ogni rebase rischioso e il ripristino diventa un solo comando. Esegui database o strumenti nei container? Guarda il nostro tutorial Docker per principianti (in inglese).

Conclusioni

Il merge conserva la verità, il rebase la tiene in ordine. Usa il rebase per aggiornare il tuo branch, il merge per consegnarlo e non riscrivere mai una cronologia da cui dipendono altri.

Domande frequenti

Qual è la differenza tra git merge e git rebase?

Merge combina due branch con un commit di merge e mantiene tutti i commit esistenti. Rebase sposta i tuoi commit sopra un altro branch e li riscrive, producendo una cronologia lineare.

Devo usare merge o rebase?

Fai il rebase del tuo branch di funzionalità per restare aggiornato e il merge quando lo consegni a un branch condiviso come main. Usa il merge ogni volta che altri condividono il branch.

Git rebase è pericoloso?

È sicuro sui branch privati e rischioso su quelli condivisi, perché riscrive gli hash dei commit. Usa un branch di backup e il reflog per recuperare se qualcosa va storto.

Cosa fa force-with-lease?

Forza il push solo se il branch remoto è ancora dove l’hai visto l’ultima volta, così non sovrascrivi per errore i nuovi commit di un collega.

Il rebase cancella i miei commit?

No. Crea nuovi commit con le stesse modifiche, e i vecchi restano nel reflog finché Git non li pulisce.

Continua a imparare (articoli in inglese)

Lavora con Stack Quora

Ti serve aiuto con test, WordPress o SEO?

Aiutiamo i team a rilasciare software migliore e a far crescere i loro siti. Raccontaci a cosa stai lavorando e ti suggeriremo un prossimo passo chiaro.

Continua a leggere

Altre guide su test, intelligenza artificiale e sviluppo moderno

Ti è piaciuto questo articolo? Scegli un argomento e passa direttamente ai nostri tutorial più recenti.

Intelligenza artificiale

Spiegazione delle allucinazioni dell'intelligenza artificiale: perché i modelli linguistici inventano le cose e come ridurle

Spiegazione delle allucinazioni dell'intelligenza artificiale: cosa sono, perché i modelli linguistici le producono, tipi comuni, come ridurle con b…

Leggi l'articolo →
DevOps

Spiegazione delle variabili d'ambiente: file .env, segreti e configurazione eseguiti correttamente

Variabili d'ambiente spiegate con esempi Python che abbiamo eseguito: lettura e impostazione, perché ogni valore è una stringa, file .env, ereditari…

Leggi l'articolo →
Sviluppo software

Spiegazione della limitazione della velocità API: algoritmi, intestazioni e gestione degli errori 429

La limitazione della velocità dell'API spiegata con una simulazione che abbiamo eseguito: bucket di token, finestra fissa, finestra scorrevole, risp…

Leggi l'articolo →
Automazione dei test

Derisione in Python: unittest.mock, patch e gli errori che fanno mentire i test

Mocking in Python con unittest.mock, testato: Mock e return_value, side_effect, patch dove viene utilizzato un nome, specifiche e autospec, date moc…

Leggi l'articolo →
Test del software

Spiegazione della copertura del codice: copertura di linea o di filiale e cosa significa realmente il 100%.

Copertura del codice spiegata con una vera esecuzione di cover.py: copertura di linea, ramo e condizione, lettura di un rapporto, perché la copertur…

Leggi l'articolo →
Database e SQL

DELETE vs TRUNCATE vs DROP in SQL: differenze, rollback e quando utilizzarli

DELETE vs TRUNCATE vs DROP spiegato con SQL testato: cosa rimuove, rollback, trigger, reimpostazione dell'identità, velocità e come differiscono Pos…

Leggi l'articolo →
Database e SQL

Spiegazione delle visualizzazioni SQL: crea, utilizza ed evita le insidie, con esempi

Viste SQL spiegate con le query che abbiamo eseguito: creazione di una vista, risultati in tempo reale, nascondere colonne, prestazioni, viste aggio…

Leggi l'articolo →
Sviluppo software

Interfaccia TypeScript e tipo: differenze reali, testate con il compilatore

Interfaccia TypeScript vs tipo, verificata con il vero compilatore: cosa possono fare entrambi, cosa può fare solo uno, fusione delle dichiarazioni,…

Leggi l'articolo →
Sviluppo software

Spiegazione di Python *args e **kwargs: funzioni flessibili con esempi chiari

Python *args e **kwargs spiegati con il codice che abbiamo eseguito: compressione e decompressione, ordine dei parametri, argomenti solo per parole …

Leggi l'articolo →
Sviluppo software

Funzioni Lambda Python: sintassi, usi reali e quando non usarli

Funzioni lambda Python spiegate con il codice che abbiamo eseguito: sintassi, ordinamento con chiave, mappa e filtro, chiusure, trap dell'associazio…

Leggi l'articolo →
Intelligenza artificiale

Cosa sono gli agenti AI? Come funzionano, con un semplice ciclo di agenti che puoi eseguire

Cosa sono gli agenti IA? Una semplice guida al ciclo dell'agente, agli strumenti, alla memoria e ai guardrail, con un piccolo ciclo Python che abbia…

Leggi l'articolo →
DevOps

Monitoraggio vs osservabilità: la vera differenza, con log, metriche e tracce

Spiegazione del monitoraggio e dell'osservabilità: errori noti e sconosciuti, log, metriche e tracce, una procedura dettagliata sugli incidenti di p…

Leggi l'articolo →
DevOps

Volumi Docker e montaggi di associazione: mantenere i dati del contenitore nel modo giusto

Volumi Docker e montaggi di collegamento spiegati: perché i dati del contenitore scompaiono, volumi denominati, montaggi di collegamento, tmpfs, ese…

Leggi l'articolo →
Automazione dei test

TDD vs BDD: differenze chiave, una caratteristica costruita in entrambi i modi e quando utilizzarli ciascuno

TDD vs BDD spiegato con una funzione di sconto costruita in entrambi i modi: refactoring rosso-verde con il codice che abbiamo eseguito, scenari "Da…

Leggi l'articolo →
Sviluppo software

Git merge vs rebase: differenze, esempi e quando usare ciascuno

Git merge vs rebase spiegato con output reale del log, una tabella di confronto, la regola d'oro del rebase e un flusso di lavoro sicuro per i team.

Leggi l'articolo →
Sviluppo software

List comprehension in Python: sintassi, esempi e quando evitarla

List comprehension in Python spiegata: sintassi, filtri, if-else, cicli annidati, tempi misurati e i casi in cui un normale ciclo for è meglio.

Leggi l'articolo →
Database e SQL

SQL JOIN spiegati con esempi (Inner, Left, Right, Full)

Capisci i JOIN SQL passo dopo passo con tabelle e query di esempio: INNER, LEFT, RIGHT, FULL, CROSS e SELF, con errori comuni e consigli sulle prest…

Leggi l'articolo →