conflits de fusion
Apprenez ce qui cause les conflits de fusion Git, comment lire les marqueurs et comment les résoudre, annuler ou prévenir avec les bonnes commandes.
Un conflit de fusion survient lorsque Git ne peut pas réconcilier automatiquement deux ensembles de modifications. Il se produit lorsque deux branches modifient les mêmes lignes du même fichier de façons différentes, ou lorsqu'une branche supprime un fichier que l'autre branche a modifié. Git ne pouvant pas savoir quelle version est correcte, il interrompt la fusion et vous laisse prendre la décision.
Cette page explique pourquoi les conflits surviennent, comment en reproduire un, comment lire les marqueurs que Git insère dans vos fichiers, et les différentes façons de résoudre, d'annuler ou même d'éviter un conflit. La commande git merge est celle qui combine deux branches et c'est là que la plupart des conflits apparaissent.
Git gère les fusions mieux que la plupart des systèmes de contrôle de version et intègre les modifications automatiquement chaque fois que les deux côtés touchent des parties différentes d'un fichier. Un conflit n'est donc pas une erreur dans votre flux de travail — c'est Git qui demande une décision humaine. Lorsqu'il ne peut pas décider, il marque le fichier comme en conflit et arrête la fusion afin que rien ne soit perdu.

Quand les conflits surviennent-ils ?
Toute fusion ne produit pas nécessairement un conflit. Savoir quand un conflit est probable vous aide à éviter les mauvaises surprises :
- Les mêmes lignes modifiées des deux côtés — le cas classique. Deux branches modifient différemment la même ligne de
example.txt. - Un fichier modifié sur une branche et supprimé sur l'autre — Git ne peut pas décider s'il faut conserver les modifications ou honorer la suppression.
- Des différences d'espaces blancs, de fins de ligne ou d'encodage — des modifications qui semblent identiques peuvent quand même entrer en conflit si les octets diffèrent.
Lorsque les deux branches touchent des lignes différentes ou des fichiers différents, Git les fusionne automatiquement sans aucun conflit.
Interruptions courantes lors d'une fusion
Git peut interrompre une fusion à deux moments distincts, et les deux cas nécessitent des corrections différentes. Il est utile de savoir lequel vous avez devant vous.
Échec de fusion au démarrage
Git refuse de commencer une fusion lorsque des modifications non validées dans votre répertoire de travail ou la zone de transit seraient écrasées par les commits entrants. Il ne s'agit pas d'un conflit de contenu — c'est Git qui protège un travail que vous n'avez pas encore validé. Pour reprendre le contrôle de votre état local, utilisez git stash (pour mettre les modifications de côté), git commit (pour les sauvegarder), git checkout ou git reset (pour les ignorer), puis relancez la fusion. Le message ressemble à ceci :
error: Your local changes to the following files would be overwritten by merge:
example.txt
Please commit your changes or stash them before you merge.
AbortingÉchec pendant la fusion
Un échec pendant la fusion signifie que Git a commencé à combiner les branches mais a rencontré un véritable conflit de contenu entre votre branche actuelle et la branche que vous fusionnez. La fusion est laissée à moitié terminée pour que vous puissiez la résoudre. Le message ressemble à ceci :
CONFLICT (content): Merge conflict in example.txt
Automatic merge failed; fix conflicts and then commit the result.Créer un conflit de fusion
Vous pouvez reproduire un conflit dans un dépôt temporaire pour pratiquer sa résolution en toute sécurité. Commencez par créer un dépôt avec un seul fichier validé :
mkdir test-dir
cd test-dir
git init .
echo "some content" > example.txt
git add example.txt
git commit -m "initial commit"
[master (root-commit) a45c22d] initial commit
1 file changed, 1 insertion(+)
create mode 100644 example.txtCela crée un répertoire nommé test-dir, initialise un dépôt et valide example.txt avec la ligne some content. Nous avons maintenant une branche (master) et un fichier. Ensuite, créez une deuxième branche et modifiez la même ligne — c'est ce qui rend le conflit possible :
git checkout -b branch_to_merge
echo "completely different content to merge later" > example.txt
git commit -m "edit the content of example.txt to make a conflict"
[branch_to_merge 4221135] edit the content of example.txt to make a conflict
1 file changed, 1 insertion(+), 1 deletion(-)git checkout -b branch_to_merge crée la branche et bascule vers elle. Nous écrasons example.txt et validons la modification, donc cette branche a maintenant une version différente de cette ligne. Revenez sur master et modifiez le même fichier d'une façon différente :
git checkout master
Switched to branch 'master'
echo "content to add" >> example.txt
git commit -m "added content to example.txt"
[master 11ab34b] added content to example.txt
1 file changed, 1 insertion(+)Les deux branches ont maintenant leur propre commit qui touche example.txt. Lancez la fusion, et Git signale le conflit qu'il ne peut pas résoudre seul :
git merge branch_to_merge
Auto-merging example.txt
CONFLICT (content): Merge conflict in example.txt
Automatic merge failed; fix conflicts and then commit the result.Identifier les conflits de fusion
Outre le message affiché par la fusion, git status vous indique exactement quels fichiers sont en conflit en les listant sous Unmerged paths :
git status
On branch master
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: example.txtboth modified signifie que le fichier a été modifié des deux côtés. Ouvrez ou affichez le fichier avec cat pour voir les marqueurs de conflit que Git a insérés :
cat example.txt
<<<<<<< HEAD
some content
content to add
=======
completely different content to merge later
>>>>>>> branch_to_mergeLisez les trois marqueurs ainsi :
<<<<<<< HEAD— début du conflit. Tout ce qui se trouve en dessous jusqu'à=======correspond à votre branche actuelle (master, vers laquelleHEADpointe).=======— la ligne de séparation entre les deux versions.>>>>>>> branch_to_merge— fin du conflit. Les lignes entre=======et ce marqueur proviennent de la branche que vous fusionnez.
Pour annuler entièrement la fusion et revenir à l'état exact d'avant le début, exécutez git merge --abort. Vous pouvez en savoir plus sur les marqueurs sur la page git merge.
Résoudre les conflits de fusion
Résolution manuelle
Ouvrez le fichier en conflit dans votre éditeur, décidez quel doit être le contenu final et supprimez les trois marqueurs (<<<<<<<, =======, >>>>>>>). Vous pouvez conserver un côté, l'autre, ou une combinaison manuelle des deux. Par exemple, conserver les deux morceaux de contenu donne :
some content
content to add
completely different content to merge laterUne fois les marqueurs supprimés et le contenu correct, indexez le fichier avec git add et validez pour terminer la fusion :
git add example.txt
git commit -m "resolve merge conflict in example.txt"L'exécution de git commit après un conflit crée un commit de fusion qui relie les deux historiques de branches.
Résolution en choisissant un côté
Lorsque vous souhaitez simplement conserver la version d'un fichier d'une branche entièrement, vous n'avez pas à modifier manuellement. Extrayez le côté que vous voulez, puis indexez et validez :
git checkout --ours example.txt # keep the version from the current branch (master)
git checkout --theirs example.txt # keep the version from the incoming branch
git add example.txt--ours conserve le contenu de votre branche actuelle ; --theirs conserve le contenu de la branche entrante.
Résolution avec un outil visuel
Pour les conflits plus importants, git mergetool ouvre un outil de comparaison côte à côte configuré afin que vous puissiez résoudre les conflits de façon interactive plutôt qu'en modifiant manuellement les marqueurs. Exécutez git mergetool pour parcourir tous les fichiers en conflit, ou git mergetool example.txt pour un fichier spécifique.
Annuler une fusion
Si vous décidez que la fusion était une erreur, ou que vous préférez repartir à zéro avec un répertoire de travail propre, annulez-la :
git merge --abortCela restaure votre branche et votre répertoire de travail dans l'état exact où ils se trouvaient avant d'exécuter git merge — sans marqueurs, sans fichiers à moitié fusionnés. Utilisez-le dès que le conflit est plus que vous ne souhaitez gérer pour l'instant.
Prévenir les conflits de fusion
Les conflits sont normaux, mais vous pouvez réduire leur fréquence et leur gravité :
- Fusionnez ou faites un rebase depuis la branche principale souvent pour que votre branche ne s'éloigne jamais trop d'elle.
- Gardez les commits petits et ciblés, et évitez les reformatages massifs dans le même changement que les modifications logiques.
- Communiquez pour que deux personnes ne réécrivent pas le même fichier en même temps.
- Prévisualisez le chevauchement avec git diff avant la fusion pour voir quelles lignes pourraient entrer en collision.
Aide-mémoire des commandes
Voici les commandes que vous utiliserez le plus souvent pour gérer les conflits :
| Outil | Description |
|---|---|
git status | Permet de trouver les fichiers en conflit. |
git mergetool | Ouvre un outil de comparaison visuel pour résoudre les conflits de façon interactive. |
git diff | Affiche les différences entre les commits, les branches ou les fichiers pour aider à identifier les conflits potentiels avant la fusion. |
git checkout --ours/--theirs | Remplace le fichier en conflit par le contenu de la branche actuelle ou entrante. |
git reset --mixed | Désindexe les fichiers mais laisse le répertoire de travail inchangé. |
git merge --abort | Annule la fusion en cours et restaure le répertoire de travail dans l'état précédant le début de la fusion. |
git reset | Réinitialise l'index pour correspondre à HEAD, ce qui aide à désindexer les fichiers en conflit. |