Aller au contenu principal

Gestion des branches

Introduction

Quand on travaille sur un projet, on veut souvent développer une nouvelle fonctionnalité ou corriger un bug sans risquer de casser le code qui fonctionne déjà. C'est exactement le rôle des branches dans Git.

Objectifs de ce cours :

  • Comprendre ce qu'est une branche Git et pourquoi les utiliser
  • Créer et naviguer entre les branches avec git branch et git switch
  • Fusionner des branches avec git merge
  • Résoudre les conflits de fusion

1. Qu'est-ce qu'une Branche?

Concept

Une branche est une ligne de développement indépendante. Elle permet de travailler sur des modifications sans affecter la branche principale (main).

Analogie

Imaginez un livre dont vous écrivez la suite. La branche main est le manuscrit officiel. Quand vous voulez essayer un nouveau chapitre, vous faites une photocopie et travaillez dessus. Si le chapitre est bon, vous l'intégrez dans le manuscrit. Sinon, vous jetez la photocopie sans avoir abîmé l'original.

Visualisation

A---B---C (fonctionnalite-login)
/
main: D---E---F---G
\
H---I (fix-bug-42)

Chaque lettre est un commit. On voit trois branches : main, fonctionnalite-login et fix-bug-42, qui évoluent en parallèle.


2. Commandes de Base pour les Branches

Lister les branches

git branch

La branche courante est marquée d'un * :

fix-bug-42
fonctionnalite-login
* main

Créer une branche

git branch nom-de-la-branche

Cela crée la branche mais ne bascule pas dessus.

Supprimer une branche

# Supprimer une branche déjà fusionnée
git branch -d nom-de-la-branche

# Forcer la suppression (même si pas fusionnée)
git branch -D nom-de-la-branche

3. Naviguer entre les Branches avec git switch

Pourquoi git switch plutôt que git checkout?

La commande git checkout fait trop de choses différentes (changer de branche, restaurer des fichiers, etc.). Git a introduit git switch pour clarifier l'intention : changer de branche.

Changer de branche

git switch nom-de-la-branche

Exemple :

git switch fonctionnalite-login

Git met à jour les fichiers dans votre répertoire de travail pour refléter l'état de cette branche.

Créer et basculer en une seule commande

git switch -c nouvelle-branche

C'est l'équivalent de :

git branch nouvelle-branche
git switch nouvelle-branche

Revenir à la branche précédente

git switch -

Exemple complet

# On est sur main
git switch -c ajout-validation

# On fait nos modifications
git add .
git commit -m "Ajouter validation du courriel"

# On revient sur main
git switch main

IMPORTANT : Avant de changer de branche, assurez-vous que vos modifications sont commitées ou mises de côté (git stash). Sinon, Git refusera le changement si des conflits sont possibles.


4. Fusionner des Branches avec git merge

Concept

Le merge (fusion) intègre les modifications d'une branche dans une autre. Typiquement, on fusionne une branche de fonctionnalité dans main quand le travail est terminé.

Workflow typique

# 1. Se placer sur la branche qui REÇOIT les modifications
git switch main

# 2. Fusionner la branche source
git merge ajout-validation

Après le merge, les commits de ajout-validation sont intégrés dans main.

Visualisation d'un merge

Avant :

A---B---C (ajout-validation)
/
main: D---E

Après git merge ajout-validation (depuis main) :

A---B---C (ajout-validation)
/ \
main: D---E---------M (M = commit de merge)

Fast-Forward Merge

Si main n'a eu aucun nouveau commit depuis la création de la branche, Git fait un fast-forward : il avance simplement le pointeur de main.

Avant :

main: D---E
\
A---B---C (ajout-validation)

Après fast-forward merge :

main: D---E---A---B---C

Pas de commit de merge supplémentaire. L'historique reste linéaire.


5. Résoudre les Conflits de Fusion

Quand un conflit survient-il?

Un conflit arrive quand les deux branches ont modifié la même partie du même fichier. Git ne peut pas décider automatiquement quelle version garder.

Exemple de conflit

Sur main, le fichier Utilisateur.java contient :

public String getNom() {
return nom;
}

Sur la branche validation, on a changé pour :

public String getNom() {
return nom.trim();
}

Sur main, quelqu'un d'autre a changé pour :

public String getNom() {
return nom.toUpperCase();
}

Ce que Git affiche

Quand on fait git merge validation depuis main :

Auto-merging Utilisateur.java
CONFLICT (content): Merge conflict in Utilisateur.java
Automatic merge failed; fix conflicts and then commit the result.

Le fichier contient maintenant des marqueurs de conflit :

public String getNom() {
<<<<<<< HEAD
return nom.toUpperCase();
=======
return nom.trim();
>>>>>>> validation
}
  • <<<<<<< HEAD : Version de la branche courante (main)
  • ======= : Séparateur
  • >>>>>>> validation : Version de la branche qu'on fusionne

Résoudre le conflit

  1. Ouvrir le fichier et choisir la bonne version (ou combiner les deux)
  2. Supprimer les marqueurs de conflit
  3. Commiter le résultat
// Résolution : on combine les deux
public String getNom() {
return nom.trim().toUpperCase();
}
git add Utilisateur.java
git commit -m "Résoudre conflit: combiner trim et toUpperCase dans getNom"

Résolution dans IntelliJ / VS Code

Les IDE modernes offrent une interface visuelle pour résoudre les conflits. Ils affichent les deux versions côte à côte et permettent de choisir ou combiner les changements.

Dans IntelliJ :

  1. Cliquer sur "Resolve Conflicts" dans la notification
  2. Choisir "Accept Yours", "Accept Theirs" ou "Merge" pour chaque conflit

6. Convention de Nommage des Branches

Donner un nom clair à ses branches facilite la collaboration.

Conventions courantes :

PréfixeUsageExemple
feature/Nouvelle fonctionnalitéfeature/ajout-login
fix/Correction de bugfix/null-pointer-email
refactor/Refactoringrefactor/extraction-methode
test/Ajout de teststest/couverture-utilisateur

BON :

git switch -c feature/ajout-validation-courriel
git switch -c fix/crash-liste-vide

MAUVAIS :

git switch -c ma-branche
git switch -c test123
git switch -c aaa

7. Workflow Complet : Exemple Pratique

Voici un exemple de bout en bout pour ajouter une fonctionnalité dans un projet.

# 1. S'assurer d'être à jour sur main
git switch main
git pull

# 2. Créer une branche pour la fonctionnalité
git switch -c feature/ajout-age-utilisateur

# 3. Faire les modifications dans le code
# ... modifier Utilisateur.java ...

# 4. Vérifier les changements
git status
git diff

# 5. Commiter
git add Utilisateur.java
git commit -m "Ajouter méthode getAge dans Utilisateur"

# 6. Revenir sur main et fusionner
git switch main
git merge feature/ajout-age-utilisateur

# 7. Supprimer la branche (elle a été fusionnée)
git branch -d feature/ajout-age-utilisateur

# 8. Pousser main
git push

8. Pousser et Supprimer une Branche sur le Dépôt Distant

Pousser une branche absente sur origin

Quand on crée une branche localement avec git switch -c, elle n'existe pas encore sur le dépôt distant. La première fois qu'on veut la pousser, Git ne sait pas vers quelle branche distante envoyer les commits. Il faut lui indiquer explicitement avec --set-upstream (ou -u) :

git push -u origin nom-de-la-branche

L'option -u associe la branche locale à la branche distante. Les fois suivantes, un simple git push suffit.

Exemple :

git switch -c feature/ajout-recherche

# ... commits ...

# Première poussée : la branche n'existe pas encore sur origin
git push -u origin feature/ajout-recherche

Git confirme la création de la branche distante :

Total 0 (delta 0), reused 0 (delta 0), pack-reused 0
To github.com:utilisateur/projet.git
* [new branch] feature/ajout-recherche -> feature/ajout-recherche
Branch 'feature/ajout-recherche' set up to track remote branch 'feature/ajout-recherche' from 'origin'.

Supprimer une branche sur origin

Une fois une branche fusionnée (via un merge ou une pull request), il est bon de la supprimer également sur le dépôt distant pour garder le projet propre.

git push origin --delete nom-de-la-branche

Exemple :

git push origin --delete feature/ajout-recherche

Git confirme la suppression :

To github.com:utilisateur/projet.git
- [deleted] feature/ajout-recherche
remarque

Supprimer la branche distante n'affecte pas la branche locale. Pour supprimer les deux, il faut aussi faire git branch -d nom-de-la-branche.

Voir les branches distantes

# Lister les branches distantes
git branch -r

# Lister toutes les branches (locales et distantes)
git branch -a

9. Bonnes Pratiques

BON

  1. Une branche par tâche : Ne pas mélanger plusieurs fonctionnalités dans une branche
  2. Noms descriptifs : Le nom de la branche doit indiquer ce qu'on y fait
  3. Commits réguliers : Commiter souvent avec des messages clairs
  4. Fusionner souvent : Ne pas laisser une branche diverger trop longtemps de main
  5. Supprimer après fusion : Nettoyer les branches qui ne servent plus

MAUVAIS

  1. Travailler directement sur main : Toujours créer une branche
  2. Branches géantes : Une branche qui vit des semaines avec des centaines de modifications
  3. Noms vagues : test, temp, ma-branche
  4. Accumuler les branches mortes : Supprimer les branches fusionnées

10. Résumé des Commandes

CommandeDescription
git branchLister les branches locales
git branch -rLister les branches distantes
git branch -aLister toutes les branches
git branch nomCréer une branche
git branch -d nomSupprimer une branche fusionnée
git branch -D nomForcer la suppression d'une branche
git switch nomBasculer sur une branche
git switch -c nomCréer et basculer sur une branche
git switch -Revenir à la branche précédente
git merge nomFusionner une branche dans la branche courante
git push -u origin nomPousser une nouvelle branche sur origin
git push origin --delete nomSupprimer une branche sur origin

Ressources