Résolution de conflits
Apprenez à identifier et résoudre les conflits de fusion qui surviennent lors de la collaboration.
Résolution de conflits
Les conflits Git sont inévitables dans le développement collaboratif. Ce tutoriel vous apprendra à comprendre, identifier et résoudre efficacement les conflits de fusion pour maintenir un workflow fluide en équipe.
Qu’est-ce qu’un conflit Git ?
Un conflit survient quand Git ne peut pas fusionner automatiquement les modifications de deux branches parce qu’elles modifient les mêmes lignes de code de manière incompatible.
gitgraph
commit id: "Initial"
branch feature-a
checkout feature-a
commit id: "Modify line 5"
checkout main
branch feature-b
checkout feature-b
commit id: "Modify line 5 differently"
checkout main
merge feature-a
merge feature-b id: "CONFLICT!"
Types de conflits
1. Conflits de contenu
Modifications simultanées des mêmes lignes :
# Branche A modifie :
function greet() {
return "Hello World!";
}
# Branche B modifie :
function greet() {
return "Bonjour le monde!";
}
2. Conflits de renommage
# Branche A : renomme file.txt en document.txt
# Branche B : modifie le contenu de file.txt
# Résultat : Git ne sait pas quoi faire
3. Conflits de suppression
# Branche A : supprime file.txt
# Branche B : modifie file.txt
# Résultat : Conflit de suppression/modification
Anatomie d’un conflit
Marqueurs de conflit
<<<<<<< HEAD
function calculateTotal(items) {
return items.reduce((sum, item) => sum + item.price, 0);
}
=======
function calculateTotal(items) {
let total = 0;
for (let item of items) {
total += item.price;
}
return total;
}
>>>>>>> feature/new-calculation
Explication des marqueurs :
<<<<<<< HEAD
: Début de votre version (branche courante)=======
: Séparateur entre les versions>>>>>>> feature/new-calculation
: Fin de la version de l’autre branche
Identifier les conflits
Commandes de diagnostic
# Voir l'état des conflits
git status
# Lister les fichiers en conflit
git diff --name-only --diff-filter=U
# Voir les détails des conflits
git diff
# Voir les conflits avec plus de contexte
git diff --conflict=diff3
Sortie typique de git status
On branch main
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: src/calculator.js
both modified: README.md
no changes added to commit (use "git add" or "git commit -a")
Stratégies de résolution
1. Résolution manuelle
# 1. Identifier les fichiers en conflit
git status
# 2. Ouvrir le fichier et éditer manuellement
# Supprimer les marqueurs <<<<<<, =======, >>>>>>>
# Garder le code désiré
# 3. Marquer comme résolu
git add fichier-resolu.js
# 4. Finaliser la fusion
git commit
2. Choisir une version complète
# Garder votre version (HEAD)
git checkout --ours fichier.js
git add fichier.js
# Garder leur version
git checkout --theirs fichier.js
git add fichier.js
# Finaliser
git commit
3. Outils de merge
# Configurer un outil de merge
git config --global merge.tool vimdiff
# Lancer l'outil
git mergetool
# Autres outils populaires
git config --global merge.tool vscode
git config --global merge.tool kdiff3
git config --global merge.tool meld
Résolution étape par étape
Exemple pratique complet
# Situation : Conflit lors d'un merge
git merge feature/user-profile
# Auto-merging src/user.js
# CONFLICT (content): Merge conflict in src/user.js
# Automatic merge failed; fix conflicts and then commit the result.
# 1. Examiner le conflit
git status
cat src/user.js
Contenu du fichier avec conflit :
class User {
constructor(name, email) {
this.name = name;
this.email = email;
<<<<<<< HEAD
this.id = Math.random().toString(36);
this.createdAt = new Date();
=======
this.id = generateUniqueId();
this.timestamp = Date.now();
>>>>>>> feature/user-profile
}
}
# 2. Résoudre le conflit (édition manuelle)
# Décider de combiner les deux approches
Résolution :
class User {
constructor(name, email) {
this.name = name;
this.email = email;
this.id = generateUniqueId(); // Utiliser la fonction plus robuste
this.createdAt = new Date(); // Garder le format Date
this.timestamp = Date.now(); // Ajouter aussi le timestamp
}
}
# 3. Marquer comme résolu
git add src/user.js
# 4. Vérifier que tous les conflits sont résolus
git status
# 5. Finaliser le merge
git commit -m "Merge feature/user-profile
Resolved conflicts in user.js by combining both ID generation
approaches and keeping both timestamp formats for compatibility."
Outils de résolution
VS Code
VS Code offre une interface intuitive pour résoudre les conflits :
// settings.json
{
"git.mergeEditor": true,
"merge-conflict.autoNavigateNextConflict.enabled": true
}
Fonctionnalités :
- Accept Current Change : Garder votre version
- Accept Incoming Change : Garder leur version
- Accept Both Changes : Combiner les deux
- Compare Changes : Voir les différences côte à côte
GitKraken
Interface graphique avancée :
- Visualisation des branches et conflits
- Éditeur de merge intégré
- Historique des résolutions
Ligne de commande avec vimdiff
# Configuration
git config --global merge.tool vimdiff
# Utilisation
git mergetool
# Navigation dans vimdiff
# :diffget LOCAL - Prendre la version locale
# :diffget REMOTE - Prendre la version distante
# :diffget BASE - Prendre la version de base
Prévention des conflits
Bonnes pratiques
-
Synchronisation fréquente
# Récupérer régulièrement les changements git fetch origin git merge origin/main
-
Branches courtes
# Éviter les branches de longue durée # Merger fréquemment les petites fonctionnalités
-
Communication en équipe
# Coordonner les modifications sur les mêmes fichiers # Utiliser les issues GitHub pour planifier
-
Rebase avant merge
git fetch origin git rebase origin/main # Résoudre les conflits un par un git push --force-with-lease origin feature-branch
Organisation du code
// Éviter les conflits en structurant le code
// Séparer les fonctionnalités en modules distincts
// ❌ Tout dans un fichier
// app.js (500 lignes)
// ✅ Modules séparés
// auth.js
// user.js
// api.js
// utils.js
Conflits avancés
Conflits lors du rebase
# Démarrer un rebase
git rebase main
# En cas de conflit
# 1. Résoudre le conflit
# 2. Ajouter les fichiers résolus
git add .
# 3. Continuer le rebase
git rebase --continue
# Ou abandonner
git rebase --abort
Conflits avec cherry-pick
# Cherry-pick avec conflit
git cherry-pick abc1234
# Résoudre et continuer
git add .
git cherry-pick --continue
# Ou abandonner
git cherry-pick --abort
Conflits de merge vs rebase
Merge conflicts :
- Résolus en une fois
- Historique préservé
- Commit de merge créé
Rebase conflicts :
- Résolus commit par commit
- Historique linéaire
- Pas de commit de merge
Exercices pratiques
Exercice 1 : Conflit simple
# 1. Créer un dépôt de test
mkdir conflict-demo
cd conflict-demo
git init
# 2. Créer un fichier initial
echo "function greet() {
return 'Hello';
}" > greet.js
git add greet.js
git commit -m "Initial greeting function"
# 3. Créer deux branches avec modifications conflictuelles
git checkout -b feature-french
echo "function greet() {
return 'Bonjour';
}" > greet.js
git add greet.js
git commit -m "Add French greeting"
git checkout main
git checkout -b feature-spanish
echo "function greet() {
return 'Hola';
}" > greet.js
git add greet.js
git commit -m "Add Spanish greeting"
# 4. Merger et résoudre le conflit
git checkout main
git merge feature-french
git merge feature-spanish
# Conflit attendu !
# 5. Résoudre en combinant les langues
echo "function greet(language = 'en') {
const greetings = {
'en': 'Hello',
'fr': 'Bonjour',
'es': 'Hola'
};
return greetings[language] || greetings['en'];
}" > greet.js
git add greet.js
git commit -m "Resolve conflict by supporting multiple languages"
Exercice 2 : Conflit complexe avec plusieurs fichiers
# 1. Créer un projet avec plusieurs fichiers
echo "# My App" > README.md
echo "const version = '1.0.0';" > version.js
echo "function add(a, b) { return a + b; }" > math.js
git add .
git commit -m "Initial project setup"
# 2. Branche A : Modifications multiples
git checkout -b feature-updates
echo "# My Awesome App
Version 2.0 with new features!" > README.md
echo "const version = '2.0.0';" > version.js
echo "function add(a, b) {
if (typeof a !== 'number' || typeof b !== 'number') {
throw new Error('Invalid input');
}
return a + b;
}" > math.js
git add .
git commit -m "Update to version 2.0 with validation"
# 3. Branche B : Modifications différentes
git checkout main
git checkout -b feature-improvements
echo "# My App
Now with better performance!" > README.md
echo "const version = '1.1.0';" > version.js
echo "function add(a, b) {
// Optimized addition
return Number(a) + Number(b);
}" > math.js
git add .
git commit -m "Performance improvements v1.1"
# 4. Merger et résoudre tous les conflits
git checkout main
git merge feature-updates
git merge feature-improvements
# Résoudre chaque fichier individuellement
Stratégies d’équipe
Workflow avec conflits minimaux
# 1. Feature branches courtes
git checkout -b feature/small-change
# ... développement rapide ...
git push origin feature/small-change
# ... PR et merge rapide ...
# 2. Rebase avant PR
git fetch origin
git rebase origin/main
git push --force-with-lease origin feature/small-change
# 3. Merge fréquent de main
git checkout feature/long-running
git merge origin/main
# Résoudre les conflits au fur et à mesure
Communication des conflits
# Template de message pour conflit résolu
## Conflit résolu dans PR #123
**Fichiers affectés :**
- src/user.js
- src/auth.js
**Nature du conflit :**
Modifications simultanées des méthodes d'authentification
**Résolution choisie :**
Combinaison des deux approches :
- Garde la validation de feature-a
- Intègre l'optimisation de feature-b
**Tests effectués :**
- [ ] Tests unitaires passent
- [ ] Tests d'intégration OK
- [ ] Validation manuelle
cc @team-lead @reviewer
Dépannage avancé
Annuler une résolution de conflit
# Si vous avez fait une erreur dans la résolution
git reset --hard HEAD~1 # Annule le commit de merge
git merge feature-branch # Recommence le merge
Voir l’historique des conflits
# Voir les merges précédents
git log --merges --oneline
# Voir les détails d'un merge
git show commit-hash
# Voir les conflits d'un merge spécifique
git log --cc commit-hash
Résolution automatique
# Configurer des stratégies de merge
git config merge.ours.driver true # Toujours garder notre version
git config merge.theirs.driver "cp %B %A" # Toujours garder leur version
# Dans .gitattributes
*.generated merge=ours
*.config merge=theirs
Ressources supplémentaires
Outils recommandés
- Beyond Compare : Outil de diff/merge professionnel
- P4Merge : Gratuit et efficace
- Meld : Open source, multi-plateforme
- KDiff3 : Merge à 3 voies
Documentation
Conclusion
La résolution de conflits est une compétence essentielle pour tout développeur travaillant en équipe. Avec de la pratique et les bons outils, les conflits deviennent une partie normale et gérable du workflow de développement.
Dans le prochain tutoriel, nous explorerons les workflows Git avancés utilisés dans les équipes professionnelles.
Temps de lecture estimé : 30 minutes
Niveau : Intermédiaire
Étape précédente : Collaboration avec GitHub
Prochaine étape : Workflows Git avancés