Da Anonimo (non verificato) , 29 Aprile 2026

Introduzione

Quando Git non può combinare automaticamente due modifiche alla stessa regione di un file, lascia marker di conflitto nella copia di lavoro e ti permette di risolvere manualmente. I marker non sono magia; registrano esattamente cosa ha fatto ogni lato relativo a una base comune.

Anatomia

<<<<<<< HEAD
riga come è sul nostro branch
=======
riga come è sul loro branch
>>>>>>> feature/login

La sezione tra <<< e === è "ours" (il branch corrente). Tra === e >>> è "theirs". La risoluzione consiste nel mantenere il testo giusto, cancellare i marker e mettere in stage.

Marker a tre vie (stile diff3)

git config --global merge.conflictStyle diff3

Ora i marker includono anche la versione base:

<<<<<<< HEAD
nostra versione
||||||| merged common ancestor
versione base
=======
loro versione
>>>>>>> feature/login

Vedere la base spesso chiarisce cosa intendeva ogni lato. Ancora meglio, da Git 2.35:

git config --global merge.conflictStyle zdiff3

che taglia il contesto comune.

Come Git li produce

Per ogni coppia di hunk in conflitto, Git esegue un diff a tre vie tra base, ours e theirs. Se entrambi i lati hanno cambiato la stessa regione diversamente, Git scrive entrambe le versioni circondate da marker. Altrimenti il lato che ha cambiato vince automaticamente.

Risolvere

git status                       # elenca path in conflitto
modifica ogni file
git add <file>                   # marca come risolto
git commit                       # usa il messaggio preparato

Oppure usa un merge tool:

git mergetool
git config --global merge.tool meld

Ispezionare ogni lato

git show :1:path        # base
git show :2:path        # ours
git show :3:path        # theirs
git checkout --ours path
git checkout --theirs path

La sintassi colon legge direttamente dagli stage dell'index in conflitto.

Annullare

git merge --abort
git rebase --abort
git cherry-pick --abort

rerere

"Reuse recorded resolution" ricorda le tue risoluzioni di conflitto e le riapplica la prossima volta che lo stesso conflitto appare:

git config --global rerere.enabled true

Indispensabile per catene di rebase di lunga durata.

Conflitti di rename e binari

Non tutti i conflitti producono marker testuali. I conflitti rename/rename, rename/delete e modify/delete lasciano l'index in uno stato con più stage ma senza marker <<< nel file. I file binari non possono essere mergiati testualmente; entrambe le versioni vengono scritte su disco e l'index registra il conflitto:

git status
# both modified:   image.png
# deleted by us:   old.txt
# added by them:   new.txt
git checkout --ours image.png      # mantieni la nostra versione
git checkout --theirs new.txt
git add image.png new.txt

Leggi sempre git status al momento del conflitto; etichetta esplicitamente questi tipi di conflitto meno comuni.

Errori comuni

Risolvere cancellando i marker senza leggere i contenuti, accidentalmente eliminando un lato. Leggi sempre entrambe le metà e la base. Dimenticare git add dopo aver modificato; git commit rifiuterà con "unmerged paths". Trattare --ours e --theirs come identici a -X ours e -X theirs; il primo sostituisce un intero file in conflitto, il secondo è un suggerimento alla strategia di merge. Infine, copiare un file parzialmente risolto da altrove e bypassare Git; l'index ha ancora le entry stage 1/2/3 finché non fai git add.