Aller au contenu principal

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 --oneline montre 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 !