Skip to content

Tutto per WordPress, lo sviluppo web — e non solo

🐙 Errore git 'fatal: refusing to merge unrelated histories': cause e soluzione

🐙 Errore git 'fatal: refusing to merge unrelated histories': cause e soluzione

Hai eseguito git pull e, invece delle modifiche attese, il terminale ti ha accolto con una riga rossa: fatal: refusing to merge unrelated histories. Il progetto non si è aggiornato, i commit non sono stati scaricati e tu sei lì a chiederti se hai rotto la repository.

No, non l'hai rotta. Git si rifiuta semplicemente di mescolare due cronologie indipendenti, e questo è un comportamento intenzionale, non un bug. In cinque minuti non solo capirai perché si verifica questo errore, ma imparerai anche a risolverlo in qualsiasi situazione: al primo push, dopo aver perso la cartella .git e quando unisci progetti diversi.

💡 Panoramica rapida:

  • Quando Git rifiuta di unire branch non correlati e perché è corretto
  • Il flag --allow-unrelated-histories, una soluzione universale per pull, merge e primo push
  • Scenari passo passo: clonazione senza cronologia, nuova repository, rebase e force-push
  • Cosa fare se il flag non aiuta e come evitare questo errore in futuro

Cosa significa l'errore e perché Git lo genera

Git traccia la cronologia attraverso una catena di commit. Ogni commit fa riferimento al suo genitore, costruendo un grafo che Git usa per capire cosa proviene da dove. Quando fai git merge, Git cerca un antenato comune tra due branch e calcola la differenza a partire da esso.

Ma a volte semplicemente non c'è un antenato comune. Due grafi di commit non si intersecano, come due progetti separati che non hanno mai saputo l'uno dell'altro. In una situazione del genere, Git si rifiuta di unire le cronologie alla cieca e restituisce:

1fatal: refusing to merge unrelated histories

Questo non è un errore nel senso comune del termine. È una protezione: Git ti sta dicendo «Non capisco come queste due cronologie siano correlate, quindi non tiro a indovinare». La soluzione esiste ed è integrata in Git a partire dalla versione 2.9.0 (rilasciata a giugno 2016).

Due scenari tipici che portano all'errore

Primo scenario, **corruzione o cancellazione della cartella **.git. Hai clonato un progetto, hai lavorato con il codice, ma la cartella .git è stata eliminata (accidentalmente, da un antivirus o durante la copia senza file nascosti). Git perde tutta la cronologia locale e quando tenti git push o git pull tratta la tua directory di lavoro come un progetto completamente nuovo, non correlato alla repository remota.

Secondo scenario, una nuova repository incontra una esistente. Hai fatto git init, hai aggiunto diversi commit in locale, poi hai provato a collegare una repository remota che ha già una sua cronologia. Git vede due grafi di commit indipendenti e si rifiuta di mescolarli. Questo accade spesso quando inizi un progetto da zero, poi decidi di caricarlo su GitHub sopra una repository esistente, o quando trasferisci codice da un progetto a un altro.

Entrambi gli scenari si risolvono con lo stesso meccanismo, ma prima di applicarlo dovresti capire cosa vuoi ottenere esattamente: unire due cronologie in una o sostituire completamente una cronologia con un'altra.

Soluzione: il flag --allow-unrelated-histories

La chiave per risolvere il problema è il flag --allow-unrelated-histories. Dice esplicitamente a Git: «So che questi branch non hanno un antenato comune e voglio consapevolmente unirli». Il flag funziona con entrambi i comandi principali, git pull e git merge.

**Per **git pull (il caso più comune):

1git pull origin main --allow-unrelated-histories

Sostituisci main con il nome del tuo branch se è diverso (master, develop, ecc.). Git creerà un commit di merge che collega le due cronologie indipendenti. Probabilmente si aprirà un editor per il messaggio di commit, descrivi perché stai unendo le cronologie, salva e chiudi l'editor.

**Per **git merge (quando i branch sono locali):

1git merge feature-branch --allow-unrelated-histories

Dopo il merge riuscito, Git ti chiederà di fare push del risultato. Non dimenticare di farlo:

1git push origin main

Sfumatura importante: --allow-unrelated-histories non elimina i conflitti di merge. Se entrambi i branch hanno file con gli stessi nomi, Git ti chiederà comunque di risolvere i conflitti manualmente, il flag gestisce solo la connessione delle cronologie, non il contenuto dei file.

Scenari passo passo per diverse situazioni

Situazione 1: primo push su una repository remota non vuota

Hai creato un progetto in locale (git init → commit) e su GitHub c'è già una repository con README.md e .gitignore. Un git push diretto non funzionerà perché il branch remoto contiene commit che tu non hai.

Sequenza corretta:

Prima fai pull della cronologia remota e la unisci con la tua locale:

1git pull origin main --allow-unrelated-histories

Risolvi i conflitti se ce ne sono (di solito conflitti su README.md), fai un commit di merge, poi:

1git push origin main

Situazione 2: ripristino dopo la perdita di.git

La cartella .git è stata eliminata, ma la directory di lavoro è intatta. Puoi ripristinare la connessione alla repository remota senza perdere le modifiche non committate:

1git init
2git remote add origin <repository-url>
3git fetch origin
4git reset --mixed origin/main

Il comando git reset --mixed sincronizza l'indice di Git con il branch remoto, ma mantiene intatti tutti i tuoi file di lavoro. Dopodiché, aggiungi le modifiche e fai un nuovo commit:

1git add .
2git commit -m "Recovery after losing .git"
3git push origin main

Questo approccio è preferibile a --allow-unrelated-histories perché non crea un commit di merge artificiale e mantiene pulita la cronologia.

Situazione 3: rebase con cronologie non correlate

Anche il comando git rebase può generare questo errore, specialmente quando si usa il flag --preserve-merges (ora sostituito da --rebase-merges). Soluzione: aggiungi --allow-unrelated-histories:

1git rebase --rebase-merges --allow-unrelated-histories main

Ma fai attenzione: il rebase riscrive la cronologia e se qualcun altro sta lavorando con questo branch, creerai problemi. Per i branch condivisi, preferisci sempre merge.

Cosa fare se il flag non aiuta

A volte --allow-unrelated-histories funziona senza errori, ma il risultato non è quello che volevi.

Problema: il commit di merge appesantisce la cronologia. Se hai unito due grandi progetti, il grafo dei commit diventa difficile da leggere. In questo caso, considera un'alternativa: trasferire i file con conservazione della cronologia tramite git format-patch e git am:

1git format-patch --root -o patches/ HEAD
2git am patches/*.patch

Problema: dopo il merge il progetto non compila. Unire cronologie non correlate può portare a file di configurazione duplicati, conflitti di dipendenze o versioni di pacchetti incompatibili. Dopo --allow-unrelated-histories controlla sempre: dipendenze (npm install / composer install), file di configurazione (.env, config/), percorsi e import nel codice. Meglio dedicare cinque minuti alla verifica ora che affrontare build fallite in CI più tardi.

Problema: hai cambiato idea. Puoi annullare un merge di cronologie non correlate nel modo standard: git reset --hard HEAD~1 (se non hai ancora fatto push del risultato) o git revert -m 1 HEAD (se hai già fatto push).

Come evitare l'errore in futuro

Tre semplici regole che ti risparmieranno questo errore nel lavoro quotidiano.

Non eliminare .git senza assoluta necessità. Se devi copiare il codice senza cronologia, usa git archive o copia i file escludendo consapevolmente la cartella nascosta .git, non accidentalmente.

Non creare una nuova repository dentro una esistente. Se devi estrarre parte del codice in un progetto separato, usa git subtree split o git filter-branch (ora si consiglia git filter-repo). Questi strumenti conserveranno la cronologia dei file necessari e Git saprà da dove provengono.

Prima di git init in una cartella con codice, controlla sempre se c'è già una repository lì: git status. Se Git risponde fatal: not a git repository, puoi inizializzare. Se mostra lo stato, sei già dentro una repository esistente e git init non serve qui.

Per chi inizia a lavorare con Git, consigliamo la nostra guida "Guida a Git per principianti", che illustra passo passo le chiavi SSH, la creazione di repository e il flusso di lavoro completo su GitHub. E se Git non è ancora installato, inizia con la guida "Come installare Git su Windows".

⁉️🤔 Domande frequenti

Quali versioni di Git supportano --allow-unrelated-histories?

Il flag è apparso in Git 2.9.0 (giugno 2016) ed è presente in tutte le versioni successive. Se la tua versione di Git è più vecchia, aggiornala: il comando git --version mostrerà la versione corrente e git update-git-for-windows (su Windows) o il gestore di pacchetti del tuo sistema la aggiornerà all'ultima release. Il modo più semplice per controllare la versione di Git è il comando git --version nel terminale. A metà 2026, il branch corrente è la 2.48+. Se sei su Windows e Git è stato installato molto tempo fa, scarica un installer aggiornato da git-scm.com, l'aggiornamento automatico nelle vecchie versioni funzionava in modo instabile.

Posso usare il flag direttamente con git push?

No, git push non accetta --allow-unrelated-histories. Il push non crea un merge, invia solo commit esistenti. L'errore "unrelated histories" durante il push significa che il tuo branch locale e quello remoto hanno diverguto a livello di cronologia. Soluzione: prima git pull --allow-unrelated-histories, risolvi i conflitti e solo dopo fai git push. Formalmente --allow-unrelated-histories funziona con git fetch + git merge e con git pull (che internamente fa fetch + merge). Il push rimane un'operazione separata che esegui dopo il merge riuscito. Non cercare di aggirare il problema con --force, perderesti i commit di altre persone sulla repository remota.

Cosa è meglio per una cronologia pulita: merge o rebase?

Per collegare cronologie non correlate, sicuramente merge. Il rebase in questo contesto crea più problemi di quanti ne risolva: tenta di riapplicare i commit di un branch sopra un altro, ma senza un antenato comune questo porta a conflitti su ogni commit. Il merge con --allow-unrelated-histories fa esattamente ciò che serve: crea un punto di connessione tra i due grafi, dopodiché la cronologia è unificata. Eccezione: quando vuoi intenzionalmente riscrivere la cronologia e sai esattamente cosa stai facendo. Ad esempio, quando trasferisci codice da una repository a un'altra con pulizia dai vecchi commit. In questo caso git rebase --allow-unrelated-histories può avere senso, ma per il lavoro quotidiano scegli il merge.

Ho perso la cartella .git, ma ho modifiche non committate. Le perderò?

No, non le perderai. La cartella .git stessa contiene solo la cronologia e i metadati di Git, non i tuoi file di lavoro. Tutti i file modificati, nuovi e persino non committati rimarranno intatti nella directory di lavoro. La procedura di ripristino è descritta nella "Situazione 2" qui sopra: git initgit remote addgit fetchgit reset --mixed. Punto chiave: usa esattamente --mixed, non --hard. Il flag --mixed resetta l'indice ma conserva tutte le modifiche nei file. Se non sei sicuro, fai una copia di backup dell'intera cartella del progetto prima del ripristino, ci vorranno dieci secondi ed eliminerai completamente il rischio di perdita di dati in qualsiasi situazione anomala.

L'errore si verifica durante la clonazione tramite IDE. È lo stesso problema?

Sì, lo stesso. Alcuni IDE (ad esempio PHPStorm, Visual Studio, vecchie versioni di IntelliJ) quando creano un progetto da un template inizializzano una nuova repository Git, poi tentano di collegare un remoto. Questo è esattamente il secondo scenario dell'inizio dell'articolo. La soluzione è la stessa: apri un terminale nella cartella del progetto ed esegui git pull origin main --allow-unrelated-histories. Dopo il merge manuale, l'IDE rileverà automaticamente il nuovo stato, ti basta aggiornare la finestra del progetto o cliccare Refresh nel pannello Git.

Bisogna temere l'errore "unrelated histories"?

No. Questo è uno degli errori Git più sicuri: non corrompe i dati, non elimina file e non impedisce di continuare a lavorare. Il flag --allow-unrelated-histories non è un espediente o una soluzione di fortuna, ma una funzionalità documentata aggiunta appositamente dagli sviluppatori di Git per i casi in cui vuoi consapevolmente collegare due cronologie indipendenti.

Una volta padroneggiato questo comando, ottieni uno strumento potente: ora puoi unire progetti con qualsiasi grado di isolamento, trasferire codice tra repository e ripristinare il lavoro dopo aver perso .git, e tutto questo senza panico e senza ricreare la repository da zero. Se Git ti ha insegnato qualcosa oggi, è che "fatal" nei suoi messaggi non significa "fatale per il progetto", significa «Non tiro a indovinare, dimmi esplicitamente cosa fare».