Retour au cours

infra / git-github

Résolution de conflits

Leçon 71 exercice

Explication

Ce que vous allez apprendre

  • Comprendre pourquoi un conflit survient et pourquoi ce n'est pas une erreur de ta part
  • Lire les marqueurs <<<<<<<, =======, >>>>>>> insérés par Git dans un fichier en conflit
  • Choisir entre garder une version entière (--ours/--theirs) ou combiner les deux intentions
  • Utiliser git blame pour comprendre le contexte d'une ligne avant de trancher
  • Finaliser une résolution avec git add puis commit ou rebase --continue

Dans quel contexte ?

Deux développeurs modifient tous les deux la fonction calculateTotal du fichier pricing.js sur des branches différentes : l'un corrige un arrondi, l'autre ajoute le calcul de la TVA. Quand la seconde branche est fusionnée dans main, Git ne sait pas laquelle des deux versions de cette fonction garder — c'est exactement le scénario que cette leçon apprend à résoudre calmement.

Ce qui se passe la plupart du temps

D'abord, le merge et le rebase, vus dans les deux leçons précédentes, se déroulent le plus souvent sans intervention humaine, parce que Git est capable de fusionner automatiquement des changements qui touchent des zones différentes d'un fichier.

Quand Git ne peut plus décider

Le conflit survient précisément quand ce n'est pas le cas : deux lignes d'historique ont modifié exactement la même portion de fichier de façon différente, et Git n'a aucun moyen de deviner laquelle des deux versions est la "bonne".

Une situation normale, pas un échec

Ce n'est pas une erreur ni un échec de ta part : c'est une situation normale du travail collaboratif, et savoir la résoudre sereinement est une compétence Git essentielle.

Prérequis

Cette leçon suppose que tu as déjà pratiqué un merge (leçon précédente) : le conflit est justement le cas particulier où ce merge ne peut pas se faire automatiquement.

Ce que fait Git quand un conflit survient

Git ne choisit pas à ta place : il insère directement dans le fichier concerné des marqueurs qui délimitent les deux versions en présence, l'une venant de ta branche actuelle, l'autre de la branche que tu intègres.

Comment lire ces marqueurs

Il faut lire ce contenu comme une question posée par Git : "voici les deux versions, laquelle veux-tu garder, ou comment veux-tu les combiner ?"

La résolution la plus simple, mais limitée

La résolution la plus naïve consiste à garder entièrement une version ou l'autre, avec --ours/--theirs, ce qui convient parfois.

Une résolution plus réfléchie

Souvent, la bonne résolution est une combinaison réfléchie des deux intentions, en comprenant pourquoi chaque changement a été fait, d'où l'intérêt de git blame pour retrouver le contexte d'une ligne avant de trancher.

MarqueurSignification
<<<<<<< HEADDébut de TA version (branche courante)
=======Séparateur entre les deux versions
>>>>>>> nom-brancheFin de la version entrante (branche fusionnée)

Piège fréquent

Oublier de supprimer les marqueurs <<<<<<<, =======, >>>>>>> après une résolution "rapide" laisse ce texte invalide directement dans le code, ce qui peut casser la compilation ou introduire un bug silencieux. Relis toujours le fichier entier avant de faire git add sur une résolution de conflit.

Le rituel de fin de résolution

Une fois les marqueurs supprimés et le fichier corrigé à la main, il ne faut pas oublier d'indiquer explicitement à Git que le conflit est résolu, avec git add sur les fichiers concernés.

Ce qui reste à faire ensuite

Il faut ensuite finaliser l'opération, avec commit, ou rebase --continue si le conflit est survenu pendant un rebase. Oublier cette étape laisse Git bloqué en plein milieu de l'opération.

Maintenant que tu sais résoudre un conflit, la leçon suivante aborde un besoin différent : mettre de côté un travail non terminé sans le committer, avec le stash.

Commandes & code

Résolution de conflits

bash
git switch main
git merge feature/pricing
# Auto-merging pricing.js
# CONFLICT (content): Merge conflict in pricing.js
# Automatic merge failed; fix conflicts and then commit the result.

git status
# both modified:   pricing.js
javascript
// pricing.js après conflit : Git insère des marqueurs délimitant les deux versions
function calculateTotal(items) {
<<<<<<< HEAD
  return items.reduce((sum, item) => sum + item.price, 0);
=======
  const subtotal = items.reduce((sum, item) => sum + item.price * item.qty, 0);
  return subtotal * 1.2; // TVA incluse
>>>>>>> feature/pricing
}
javascript
// Résolution manuelle : garder la logique correcte (souvent une combinaison des deux)
function calculateTotal(items) {
  const subtotal = items.reduce((sum, item) => sum + item.price * item.qty, 0);
  return subtotal * 1.2; // TVA incluse
}
bash
# Après résolution manuelle des marqueurs <<<<<<< ======= >>>>>>>
git add pricing.js
git commit                          # finalise le merge commit
# ou, si en plein rebase :
git rebase --continue
bash
# Outils qui aident à trancher plus vite
git diff                            # voir précisément ce qui diverge
git checkout --ours pricing.js      # garde ENTIÈREMENT la version courante (HEAD)
git checkout --theirs pricing.js    # garde ENTIÈREMENT la version entrante

# Outil visuel de résolution (VS Code, meld, kdiff3...)
git mergetool

# Voir QUI a écrit chaque ligne en conflit, pour trancher en connaissance de cause
git log --oneline -- pricing.js
git blame pricing.js

Résumé

  • Les marqueurs <<<<<<<, =======, >>>>>>> délimitent HEAD vs la branche entrante.
  • Après résolution : git add sur les fichiers corrigés, puis commit (ou rebase --continue).
  • --ours/--theirs tranchent instantanément quand une version doit primer entièrement.
  • git blame aide à comprendre l'intention derrière chaque ligne en conflit.

Exercices pratiques

1 disponible
1

Mission : trancher un conflit sans tout casser

Objectif : Lire correctement les marqueurs de conflit et choisir une résolution qui combine les deux intentions plutôt que d'en écraser une.

Contexte

Sur pricing.js, un merge entre deux branches produit un conflit dans la fonction calculateTotal : une branche corrige un arrondi, l'autre ajoute le calcul de la TVA. Un développeur pressé pense résoudre le problème avec git checkout --theirs pricing.js, sans lire le fichier.

Résoudre l’exercice →