TP3 — Branches, Merge & Résolution de conflits
Travaux Pratiques 60 min Module 02
Objectifs
À la fin de ce TP, vous aurez pratiqué :
- Créer et gérer des branches avec les conventions de nommage
- Effectuer des merges fast-forward et avec commit de merge
- Simuler et résoudre des conflits de merge
- Utiliser le rebase interactif pour nettoyer l'historique
- Visualiser l'historique de branches avec
git log --graph
Mise en place
mkdir git-tp3-branches
cd git-tp3-branches
git init
# Créer le projet de base
echo "# Application de gestion d'équipe" > README.md
Créez team.py :
class MembreEquipe:
def __init__(self, nom, role):
self.nom = nom
self.role = role
def __repr__(self):
return f"MembreEquipe({self.nom}, {self.role})"
equipe = []
def ajouter_membre(nom, role):
membre = MembreEquipe(nom, role)
equipe.append(membre)
return membre
def lister_equipe():
return [str(m) for m in equipe]
git add .
git commit -m "feat: configuration initiale de l'application d'équipe"
Partie 1 : Flux de travail avec branches de fonctionnalités
Fonctionnalité 1 : Système de recherche
# Créer une branche de fonctionnalité
git switch -c feature/recherche
# Ajouter une fonction de recherche à team.py
Ajoutez à la fin de team.py :
def rechercher_membre(query):
"""Rechercher des membres par nom ou rôle."""
resultats = []
for membre in equipe:
if query.lower() in membre.nom.lower() or query.lower() in membre.role.lower():
resultats.append(membre)
return resultats
git add team.py
git commit -m "feat(equipe): ajouter la fonctionnalité de recherche de membres"
Fonctionnalité 2 : Statistiques (sur une autre branche)
# Revenir sur main et créer une autre branche
git switch main
git switch -c feature/statistiques
Ajoutez à la fin de team.py :
def obtenir_statistiques():
"""Obtenir les statistiques de l'équipe."""
total = len(equipe)
roles = {}
for membre in equipe:
roles[membre.role] = roles.get(membre.role, 0) + 1
return {"total": total, "par_role": roles}
git add team.py
git commit -m "feat(equipe): ajouter les statistiques de l'équipe"
Partie 2 : Fusionner les branches
# Fusionner la fonctionnalité de recherche dans main
git switch main
git merge --no-ff feature/recherche -m "feat: intégration de la fonctionnalité de recherche"
# Fusionner les statistiques
git merge --no-ff feature/statistiques -m "feat: intégration des statistiques d'équipe"
# Voir le graphe des branches
git log --oneline --graph --all
# Nettoyer les branches fusionnées
git branch -d feature/recherche
git branch -d feature/statistiques
Partie 3 : Simuler et résoudre un conflit
# Créer deux branches qui vont entrer en conflit
git switch -c feature/renommage-role
Modifiez team.py — changez role en poste dans MembreEquipe :
class MembreEquipe:
def __init__(self, nom, poste): # ← changé
self.nom = nom
self.poste = poste # ← changé
def __repr__(self):
return f"MembreEquipe({self.nom}, {self.poste})" # ← changé
git add team.py
git commit -m "refactor: renommer 'role' en 'poste' dans MembreEquipe"
# Créer une branche concurrente depuis main
git switch main
git switch -c feature/validation-role
Modifiez team.py — ajoutez une validation à __init__ :
ROLES_VALIDES = ["développeur", "designer", "chef de projet", "qa"]
class MembreEquipe:
def __init__(self, nom, role):
if role not in ROLES_VALIDES:
raise ValueError(f"Role invalide: {role}. Choisissez parmi {ROLES_VALIDES}")
self.nom = nom
self.role = role
git add team.py
git commit -m "feat(equipe): ajouter la validation des rôles"
# Maintenant fusionner — cela va créer un conflit !
git switch main
git merge feature/renommage-role
git merge feature/validation-role # ← CONFLIT ici
Résoudre le conflit
git status
# both modified: team.py
Ouvrez team.py et résolvez manuellement — gardez les deux changements :
ROLES_VALIDES = ["développeur", "designer", "chef de projet", "qa"]
class MembreEquipe:
def __init__(self, nom, poste):
if poste not in ROLES_VALIDES:
raise ValueError(f"Poste invalide: {poste}. Choisissez parmi {ROLES_VALIDES}")
self.nom = nom
self.poste = poste
def __repr__(self):
return f"MembreEquipe({self.nom}, {self.poste})"
git add team.py
git commit -m "feat: intégration renommage et validation (résolution conflit)"
Partie 4 : Rebase interactif
# Créer une branche avec plusieurs petits commits à nettoyer
git switch -c feature/export
echo "# Export en CSV" >> README.md
git add README.md
git commit -m "WIP export"
# Ajouter la fonction d'export à team.py
Ajoutez à la fin de team.py :
def exporter_csv():
"""Exporter l'équipe en format CSV."""
lignes = ["nom,poste"]
for membre in equipe:
lignes.append(f"{membre.nom},{membre.poste}")
return "\n".join(lignes)
git add team.py
git commit -m "ajout export"
git add README.md
git commit -m "fix readme"
# Nettoyer avec rebase interactif
git rebase -i HEAD~3
# Dans l'éditeur, squash les 3 commits en un seul propre :
# pick xxx WIP export
# squash xxx ajout export
# squash xxx fix readme
# → Message final : "feat(equipe): ajouter la fonctionnalité d'export CSV"
# Fusionner la branche nettoyée
git switch main
git merge --no-ff feature/export
git branch -d feature/export
# Voir l'historique final propre
git log --oneline --graph
Checklist de validation
- Au moins 3 branches créées avec la convention de nommage
type/description - Un merge fast-forward et un merge avec commit de merge effectués
- Un conflit de merge créé et résolu avec succès
- Le rebase interactif utilisé pour nettoyer des commits
-
git log --graph --onelinemontre un historique propre et bien structuré
Résumé
Dans ce TP vous avez pratiqué :
- La gestion de branches multiples en parallèle
- Les différentes stratégies de merge
- La résolution de conflits réels
- Le rebase interactif pour un historique propre
Vous êtes prêt pour le Module 03 — GitHub & Dépôts distants !