Da Anonimo (non verificato) , 29 Aprile 2026

Introduzione

Git ha due esiti di merge fondamentalmente diversi: fast-forward, dove la punta di un branch viene semplicemente spostata, e a tre vie, dove viene creato un nuovo commit con due parent. La scelta dipende dal fatto che i branch siano divergenti.

Fast-forward

Se la punta di main è un antenato di feature, nessun vero merge è necessario. Git sposta semplicemente main avanti:

      A---B---C   feature
     /
main

# dopo git merge feature
A---B---C   main, feature

Comando:

git switch main
git merge feature

Per forzare un vero merge commit anche quando il fast-forward è possibile:

git merge --no-ff feature

Merge a tre vie

Quando entrambi i branch sono divergenti, Git trova la merge base (l'antenato comune più recente) e combina le modifiche da entrambi i lati:

      A---B---C   feature
     /
A---D---E   main

# dopo git merge feature
A---D---E---M   main
     \     /
      B---C   feature

La strategia di merge predefinita di Git da 2.33 è ort; prima era recursive. Entrambe calcolano un merge a tre vie per file usando la merge base.

Ispezionare

git merge-base main feature
git log --oneline --graph --all
git show --stat HEAD          # vedi il merge commit

Strategie e opzioni

git merge -X ours feature        # preferisci il nostro lato in caso di conflitti
git merge -X theirs feature      # preferisci il loro lato
git merge -X ignore-space-change feature
git merge --squash feature       # applica modifiche senza merge commit

--squash crea un singolo commit che contiene tutte le modifiche da feature, senza link parent ad esso. Utile per una storia ordinata ma perde il dettaglio per-commit.

Annullare e disfare

git merge --abort                # a metà merge, torna allo stato pre-merge
git reset --hard ORIG_HEAD       # dopo un merge finito, disfalo

Configurare la politica fast-forward

git config --global merge.ff false      # crea sempre merge commit
git config --global merge.ff only      # solo fast-forward, rifiuta altrimenti
git config --global pull.ff only       # uguale per i pull

Driver di merge e attributi

Alcuni file mergiano male con il three-way testuale (lockfile generati da macchine, documentazione generata). Configura un driver di merge personalizzato tramite .gitattributes e git config:

# .gitattributes
package-lock.json merge=ours
Gemfile.lock merge=union
git config merge.ours.driver true
git config merge.union.name "Line union merge"
git config merge.union.driver "git merge-file --union %A %O %B"

La strategia integrata union mantiene entrambi i lati; ours sceglie sempre la nostra versione; i driver personalizzati possono eseguire qualsiasi programma. Usa con parsimonia; comportamenti di merge sorprendenti confondono i revisori.

Errori comuni

Credere che il fast-forward sia in qualche modo speciale o rischioso; non lo è, è solo uno spostamento di puntatore. Usare --no-ff su ogni merge in un progetto a movimento veloce, inquinando la storia con merge commit vuoti. Usare -X ours quando intendevi --strategy=ours (che scarta interamente l'altro lato) o viceversa. Infine, modificare manualmente il messaggio del merge commit dopo il fatto e rompere il wording standardizzato "Merge branch 'X'" su cui gli strumenti fanno affidamento; se devi modificare, fallo prima di git commit.