
🐙 Erreur Git 'fatal: refusing to merge unrelated histories' : causes et solution
Vous avez exécuté git pull et, au lieu des modifications attendues, le terminal vous a affiché une ligne rouge: fatal: refusing to merge unrelated histories. Le projet ne s'est pas mis à jour, les commits n'ont pas été récupérés, et vous vous demandez si vous avez cassé le dépôt.
Non, vous ne l'avez pas cassé. Git refuse simplement de mélanger deux historiques indépendants, et c'est un comportement intentionnel, pas un bug. Dans cinq minutes, vous comprendrez non seulement pourquoi cette erreur se produit, mais vous saurez aussi la corriger dans n'importe quelle situation: lors du premier push, après avoir perdu le dossier .git et lors de la fusion de projets distincts.
💡 Aperçu rapide:
- Pourquoi Git refuse de fusionner des branches sans lien et pourquoi c'est la bonne chose à faire
- L'option
--allow-unrelated-histories, une solution universelle pourpull,mergeet le premier push - Scénarios pas à pas: clonage sans historique, nouveau dépôt, rebase et force-push
- Que faire si l'option ne suffit pas et comment éviter cette erreur à l'avenir
Ce que signifie l'erreur et pourquoi Git la déclenche
Git suit l'historique via une chaîne de commits. Chaque commit référence son parent, construisant un graphe que Git utilise pour comprendre ce qui vient d'où. Lorsque vous faites git merge, Git cherche un ancêtre commun entre deux branches et calcule la différence à partir de celui-ci.
Mais parfois, il n'y a tout simplement pas d'ancêtre commun. Deux graphes de commits ne se croisent pas, comme deux projets distincts qui n'ont jamais eu connaissance l'un de l'autre. Dans une telle situation, Git refuse de fusionner les historiques à l'aveugle et affiche:
1 fatal: refusing to merge unrelated histories
Ce n'est pas une erreur au sens habituel du terme. C'est une protection: Git vous dit «Je ne comprends pas comment ces deux historiques sont liés, donc je ne vais pas deviner.» La solution existe, et elle est intégrée à Git depuis la version 2.9.0 (publiée en juin 2016).
Deux scénarios typiques qui mènent à l'erreur
Premier scénario, **la corruption ou la suppression du dossier .git. Vous avez cloné un projet, travaillé avec le code, mais le dossier .git a été supprimé (accidentellement, par un antivirus ou lors d'une copie sans les fichiers cachés). Git perd tout l'historique local et, lors d'une tentative de git push ou git pull, traite votre répertoire de travail comme un projet complètement nouveau, sans lien avec le dépôt distant.
Deuxième scénario, un nouveau dépôt rencontre un dépôt existant. Vous avez fait git init, ajouté plusieurs commits en local, puis essayé de connecter un dépôt distant qui a déjà son propre historique. Git voit deux graphes de commits indépendants et refuse de les mélanger. Cela arrive souvent lorsque vous démarrez un projet de zéro, puis décidez de le publier sur GitHub par-dessus un dépôt existant, ou lorsque vous transférez du code d'un projet à un autre.
Les deux scénarios se résolvent par le même mécanisme, mais avant de l'appliquer, vous devez comprendre ce que vous voulez exactement accomplir: fusionner deux historiques en un seul ou remplacer complètement un historique par un autre.
Solution: l'option --allow-unrelated-histories
La clé pour corriger cela est l'option --allow-unrelated-histories. Elle indique explicitement à Git: «Je sais que ces branches n'ont pas d'ancêtre commun, et je souhaite consciemment les fusionner.» L'option fonctionne avec les deux commandes principales, git pull et git merge.
**Pour **git pull (le cas le plus courant):
1 git pull origin main --allow-unrelated-histories
Remplacez main par le nom de votre branche s'il est différent (master, develop, etc.). Git va créer un commit de fusion qui relie les deux historiques indépendants. Un éditeur va probablement s'ouvrir pour le message de commit, décrivez pourquoi vous fusionnez les historiques, sauvegardez et fermez l'éditeur.
**Pour **git merge (lorsque les branches sont locales):
1 git merge feature-branch --allow-unrelated-histories
Après une fusion réussie, Git vous invitera à pousser le résultat. N'oubliez pas de le faire:
1 git push origin main
Nuance importante: --allow-unrelated-histories ne supprime pas les conflits de fusion. Si les deux branches ont des fichiers avec les mêmes noms, Git vous demandera toujours de résoudre les conflits manuellement, l'option ne gère que la connexion des historiques, pas le contenu des fichiers.
Scénarios pas à pas pour différentes situations
Situation 1: premier push vers un dépôt distant non vide
Vous avez créé un projet en local (git init → commits), et sur GitHub il y a déjà un dépôt avec README.md et .gitignore. Un git push direct ne fonctionnera pas car la branche distante contient des commits que vous n'avez pas.
Séquence correcte:
Récupérez d'abord l'historique distant et fusionnez-le avec votre historique local:
1 git pull origin main --allow-unrelated-histories
Résolvez les conflits s'il y en a (généralement des conflits sur README.md), faites un commit de fusion, puis:
1 git push origin main
Situation 2: récupération après la perte de.git
Le dossier .git est supprimé, mais le répertoire de travail est intact. Vous pouvez restaurer la connexion au dépôt distant sans perdre les modifications non commitées:
1 git init 2 git remote add origin <repository-url> 3 git fetch origin 4 git reset --mixed origin/main
La commande git reset --mixed synchronise l'index Git avec la branche distante, mais garde tous vos fichiers de travail intacts. Après cela, ajoutez les modifications et faites un nouveau commit:
1 git add . 2 git commit -m "Recovery after losing .git" 3 git push origin main
Cette approche est préférable à --allow-unrelated-histories car elle ne crée pas de commit de fusion artificiel et garde l'historique propre.
Situation 3: rebase avec des historiques sans lien
La commande git rebase peut aussi déclencher cette erreur, surtout avec l'option --preserve-merges (maintenant remplacée par --rebase-merges). Solution, ajoutez --allow-unrelated-histories:
1 git rebase --rebase-merges --allow-unrelated-histories main
Mais soyez prudent: le rebase réécrit l'historique, et si quelqu'un d'autre travaille avec cette branche, vous allez lui créer des problèmes. Pour les branches partagées, préférez toujours merge.
Que faire si l'option ne suffit pas
Parfois, --allow-unrelated-histories s'exécute sans erreur, mais le résultat n'est pas celui que vous vouliez.
Problème: le commit de fusion encombre l'historique. Si vous avez fusionné deux grands projets, le graphe des commits devient difficile à lire. Dans ce cas, envisagez une alternative, le transfert de fichiers avec conservation de l'historique via git format-patch et git am:
1 git format-patch --root -o patches/ HEAD 2 git am patches/*.patch
Problème: après la fusion, le projet ne compile pas. Fusionner des historiques sans lien peut entraîner des doublons de fichiers de configuration, des conflits de dépendances ou des versions de paquets incompatibles. Après --allow-unrelated-histories, vérifiez toujours: les dépendances (npm install / composer install), les fichiers de configuration (.env, config/), les chemins et les imports dans le code. Mieux vaut passer cinq minutes à vérifier maintenant que de gérer des échecs de build en CI plus tard.
Problème: vous avez changé d'avis. Vous pouvez annuler une fusion d'historiques sans lien de la manière standard, git reset --hard HEAD~1 (si vous n'avez pas encore poussé le résultat) ou git revert -m 1 HEAD (si vous avez déjà poussé).
Comment éviter l'erreur à l'avenir
Trois règles simples qui vous épargneront cette erreur dans votre travail quotidien.
Ne supprimez pas .git sans nécessité absolue. Si vous devez copier du code sans l'historique, utilisez git archive ou copiez les fichiers en excluant consciemment le dossier caché .git, pas accidentellement.
Ne créez pas un nouveau dépôt à l'intérieur d'un dépôt existant. Si vous devez extraire une partie du code dans un projet séparé, utilisez git subtree split ou git filter-branch (maintenant git filter-repo est recommandé). Ces outils conserveront l'historique des fichiers nécessaires, et Git saura d'où ils viennent.
Avant de faire git init dans un dossier contenant du code, vérifiez toujours s'il y a déjà un dépôt: git status. Si Git répond fatal: not a git repository, vous pouvez initialiser. S'il affiche un statut, vous êtes déjà dans un dépôt existant et git init n'est pas nécessaire ici.
Pour ceux qui débutent avec Git, nous recommandons notre guide "Guide Git pour débutants", il explique pas à pas les clés SSH, la création de dépôt et le flux de travail complet sur GitHub. Et si Git n'est pas encore installé, commencez par le guide "Comment installer Git sur Windows".
⁉️🤔 Foire aux questions
Quelles versions de Git prennent en charge --allow-unrelated-histories?
L'option est apparue dans Git 2.9.0 (juin 2016) et est présente dans toutes les versions ultérieures. Si votre version de Git est plus ancienne, mettez-la à jour: la commande
git --versionaffichera la version actuelle, etgit update-git-for-windows(sur Windows) ou le gestionnaire de paquets de votre système effectuera la mise à jour vers la version la plus récente. Le moyen le plus simple de vérifier la version de Git est la commandegit --versiondans le terminal. À la mi-2026, la branche actuelle est la 2.48+. Si vous êtes sur Windows et que Git a été installé il y a longtemps, téléchargez un nouvel installateur depuis git-scm.com, la mise à jour automatique dans les anciennes versions fonctionnait de manière instable.
Puis-je utiliser l'option directement avec git push?
Non,
git pushn'accepte pas--allow-unrelated-histories. Push ne crée pas de fusion, il envoie seulement les commits existants. L'erreur «unrelated histories» lors d'un push signifie que votre branche locale et la branche distante ont divergé au niveau de l'historique. Solution: d'abordgit pull --allow-unrelated-histories, résolvez les conflits, et seulement ensuitegit push. Formellement,--allow-unrelated-historiesfonctionne avecgit fetch+git mergeet avecgit pull(qui fait en interne fetch + merge). Push reste une opération distincte que vous effectuez après une fusion réussie. N'essayez pas de contourner cela avec--force, vous perdriez les commits des autres sur le dépôt distant.
Qu'est-ce qui est préférable pour un historique propre: merge ou rebase?
Pour connecter des historiques sans lien, clairement
merge. Rebase dans ce contexte crée plus de problèmes qu'il n'en résout: il essaie de rejouer les commits d'une branche par-dessus une autre, mais sans ancêtre commun, cela entraîne des conflits sur chaque commit. Merge avec--allow-unrelated-historiesfait exactement ce qui est nécessaire, il crée un point de connexion unique entre deux graphes, après quoi l'historique est unifié. Exception: lorsque vous voulez intentionnellement réécrire l'historique et que vous savez exactement ce que vous faites. Par exemple, lors du transfert de code d'un dépôt à un autre avec nettoyage des anciens commits. Dans ce cas,git rebase --allow-unrelated-historiespeut avoir un sens, mais pour le travail quotidien, choisissez merge.
J'ai perdu le dossier .git, mais j'ai des modifications non commitées. Vais-je les perdre?
Non, vous ne les perdrez pas. Le dossier
.gitlui-même contient uniquement l'historique et les métadonnées Git, mais pas vos fichiers de travail. Tous les fichiers modifiés, nouveaux et même non commités resteront dans le répertoire de travail, intacts. La procédure de récupération est décrite dans la «Situation 2» ci-dessus,git init→git remote add→git fetch→git reset --mixed. Point clé: utilisez exactement--mixed, pas--hard. L'option--mixedréinitialise l'index mais préserve toutes les modifications dans les fichiers. En cas de doute, faites une copie de sauvegarde de tout le dossier du projet avant la récupération, cela prendra dix secondes et éliminera complètement le risque de perte de données dans toute situation non standard.
L'erreur se produit lors du clonage via un IDE. Est-ce le même problème?
Oui, exactement le même. Certains IDE (par exemple, PHPStorm, Visual Studio, les anciennes versions d'IntelliJ) lors de la création d'un projet à partir d'un modèle initialisent un nouveau dépôt Git, puis essaient de connecter un dépôt distant. C'est exactement le deuxième scénario du début de l'article. La solution est la même: ouvrez un terminal dans le dossier du projet et exécutez
git pull origin main --allow-unrelated-histories. Après la fusion manuelle, l'IDE détectera automatiquement le nouvel état, il suffit de rafraîchir la fenêtre du projet ou de cliquer sur Actualiser dans le panneau Git.
Faut-il craindre l'erreur «unrelated histories»?
Non. C'est l'une des erreurs Git les plus sûres, elle ne corrompt pas les données, ne supprime pas les fichiers et n'empêche pas de continuer à travailler. L'option --allow-unrelated-histories n'est pas une béquille ou une solution de contournement, mais une capacité documentée, spécifiquement ajoutée par les développeurs de Git pour les cas où vous voulez consciemment connecter deux historiques indépendants.
Une fois cette commande maîtrisée, vous gagnez un outil puissant: vous pouvez désormais fusionner des projets quel que soit leur degré d'isolement, transférer du code entre dépôts et restaurer le travail après la perte de .git, et tout cela sans panique ni recréation du dépôt de zéro. Si Git vous a appris quelque chose aujourd'hui, c'est que «fatal» dans ses messages ne signifie pas «fatal pour le projet», cela signifie «je ne vais pas deviner, dites-moi explicitement quoi faire.»



