1. Concept de branche

Une branche Git n'est rien d'autre qu'un pointeur léger vers un commit. Contrairement à SVN où une branche est une copie complète du projet, une branche Git ne coûte que 41 octets (un fichier contenant le hash SHA-1 du commit cible).

HEAD — où vous vous trouvez

HEAD est un pointeur spécial qui indique le commit (ou la branche) sur lequel vous vous trouvez actuellement. Quand vous commitez, la branche active avance automatiquement.

┌──────────────────────────────────────────────────────────┐
│                                                          │
│   Commit A ──→ Commit B ──→ Commit C                     │
│                                 ↑                        │
│                               main ← HEAD                │
│                                                          │
│  (HEAD pointe sur main, qui pointe sur commit C)         │
└──────────────────────────────────────────────────────────┘

Pourquoi utiliser des branches ?

Cas d'usageBranche recommandée
Développer une nouvelle fonctionnalitéfeature/nom-fonctionnalite
Corriger un bug en productionhotfix/description-bug
Préparer une releaserelease/1.2.0
Expérimenter une idéeexperiment/mon-idee
Code principal stablemain ou master
Intégration continuedevelop

Diagramme : branches parallèles

  A ──→ B ──→ C ──→ D ──→ G  (main)
               ↘            ↗
                E ──→ F       (feature/login)

  Chaque lettre = un commit
  G = commit de merge (deux parents : D et F)

Git branch — lister les branches

# Lister les branches locales
git branch

# Lister avec le hash du dernier commit
git branch -v

# Lister les branches déjà mergées dans main
git branch --merged main

# Lister les branches NON mergées
git branch --no-merged
Les branches Git sont gratuites : Créez-en autant que vous voulez. En équipe, la convention Git Flow ou GitHub Flow définit comment nommer et utiliser les branches pour collaborer efficacement.

2. Créer et naviguer

Créer une branche

# Créer une branche (reste sur la branche courante)
git branch feature/login

# Créer une branche et basculer dessus (syntaxe moderne - Git 2.23+)
git switch -c feature/dashboard

# Ancienne syntaxe (toujours valide)
git checkout -b feature/dashboard

# Créer une branche à partir d'un commit spécifique
git branch hotfix/crash a3f8c1d

Naviguer entre les branches

# Basculer sur une branche existante (moderne)
git switch main

# Ancienne syntaxe
git checkout main

# Revenir à la branche précédente (comme cd - en bash)
git switch -

# Basculer vers un commit détaché (detached HEAD)
git switch --detach a3f8c1d

Lister toutes les branches (locales + distantes)

# Toutes les branches locales et distantes
git branch -a

# Exemple de sortie :
* feature/login           ← branche courante (étoile)
  main
  remotes/origin/main
  remotes/origin/develop

Comparaison switch vs checkout

Actiongit switch (moderne)git checkout (classique)
Changer de branchegit switch nomgit checkout nom
Créer + basculergit switch -c nomgit checkout -b nom
Revenir en arrièregit switch -git checkout -
Detached HEADgit switch --detach hashgit checkout hash
git switch a été introduit en Git 2.23 pour séparer les responsabilités : switch pour les branches, restore pour les fichiers. git checkout faisait les deux, ce qui créait de la confusion.

3. Merge

Le merge intègre les changements d'une branche dans une autre. Git choisit automatiquement la stratégie de merge selon la situation.

Fast-Forward Merge

Quand la branche cible n'a pas divergé depuis la création de la feature branch, Git avance simplement le pointeur — pas de commit de merge créé.

# Situation initiale (pas de divergence) :
  A ──→ B ──→ C  (main)
               
               D ──→ E  (feature/login)

# Après : git switch main && git merge feature/login
  A ──→ B ──→ C ──→ D ──→ E  (main, feature/login)
  (simple avancée du pointeur — fast-forward)
# Commande de merge fast-forward
git switch main
git merge feature/login
# → Fast-forward

3-Way Merge (merge commit)

Quand les deux branches ont divergé (main a avancé depuis la création de la feature branch), Git crée un commit de merge avec deux parents.

# Situation avec divergence :
  A ──→ B ──→ C ──→ D  (main)
               
               E ──→ F  (feature/navbar)

# Après : git merge feature/navbar
  A ──→ B ──→ C ──→ D ──→ G  (main)
               
               E ──→ F  (feature/navbar)
  (G = commit de merge avec 2 parents : D et F)
# Forcer un merge commit même si fast-forward possible
git merge --no-ff feature/navbar

# Message personnalisé pour le commit de merge
git merge --no-ff -m "merge: intégrer feature/navbar" feature/navbar

Fast-Forward vs No-FF — comparaison

AspectFast-Forward--no-ff (Merge commit)
HistoriqueLinéaire (propre)Avec branches visibles
Commit de mergeNon crééCréé systématiquement
TraçabilitéPlus difficileClaire (on voit les features)
git revert d'une featureDifficile (commits éparpillés)Facile (revert du merge commit)
Recommandé pourBranches courtes, soloÉquipes, features complètes
Bonne pratique : En équipe, utilisez git merge --no-ff ou les Pull Requests (GitHub/GitLab) qui créent automatiquement un merge commit. Cela garde une trace claire de chaque feature intégrée.

4. Résolution de conflits

Un conflit survient quand deux branches ont modifié les mêmes lignes d'un même fichier. Git ne peut pas décider automatiquement quelle version garder.

Exemple de conflit

# Situation : les deux branches ont modifié navbar.js
git switch main
git merge feature/navbar

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

Marqueurs de conflit dans le fichier

// navbar.js après conflit :

function initNavbar() {
<<<<<<< HEAD
  // Version de main
  setTheme('dark');
  addMenuItems(['Accueil', 'Contact']);
=======
  // Version de feature/navbar
  setTheme('light');
  addMenuItems(['Accueil', 'Blog', 'Contact']);
>>>>>>> feature/navbar
}

Comprendre les marqueurs

MarqueurSignification
<<<<<<< HEADDébut de la version de votre branche courante (HEAD)
=======Séparateur entre les deux versions
>>>>>>> feature/navbarFin de la version de la branche mergée

Étapes de résolution

// ① Ouvrir le fichier en conflit dans votre éditeur
// ② Choisir la version correcte (ou combiner les deux) :

function initNavbar() {
  setTheme('dark');                              // ← gardé de HEAD
  addMenuItems(['Accueil', 'Blog', 'Contact']);  // ← gardé de feature
}
// ③ Supprimer TOUS les marqueurs (<<<, ===, >>>)
# ③ Marquer le conflit comme résolu
git add navbar.js

# ④ Vérifier qu'il ne reste pas de conflits
git status

# ⑤ Créer le commit de merge
git commit -m "merge: résoudre conflit navbar.js — combiner thème et menu"

Abandonner un merge

# Annuler le merge en cours (revenir à l'état avant merge)
git merge --abort

Outils visuels de merge

# Ouvrir l'outil de merge configuré
git mergetool

# Configurer VS Code comme outil de merge
git config --global merge.tool vscode
git config --global mergetool.vscode.cmd 'code --wait $MERGED'
Ne jamais committer avec des marqueurs de conflit ! Votre application planterait immédiatement. Utilisez git diff --check pour vérifier qu'il ne reste aucun marqueur avant de committer.

5. Supprimer et renommer

Supprimer une branche mergée

# Supprimer une branche locale (déjà mergée = safe)
git branch -d feature/login

# Vérifier quelles branches sont mergées dans main
git branch --merged main

Forcer la suppression

# Supprimer une branche NON mergée (perte de commits potentielle !)
git branch -D feature/abandon

# ⚠️ -D est équivalent à --delete --force
# Les commits "perdus" restent dans git reflog pendant 30 jours

Renommer une branche

# Renommer la branche courante
git branch -m nouveau-nom

# Renommer une branche spécifique
git branch -m ancien-nom nouveau-nom

# Cas pratique : renommer master en main
git branch -m master main

Supprimer une branche distante

# Supprimer la branche sur origin (distant)
git push origin --delete feature/login

# Nettoyer les références distantes obsolètes
git fetch --prune

Bonnes pratiques de nommage

PréfixeUsageExemple
feature/Nouvelle fonctionnalitéfeature/user-auth
fix/Correction de bugfix/login-crash
hotfix/Correctif urgent en prodhotfix/security-xss
release/Préparation de versionrelease/2.1.0
chore/Maintenance, refactoringchore/update-deps
docs/Documentationdocs/api-guide
Règle : Utilisez des minuscules, tirets (pas d'underscores ni espaces), et un préfixe descriptif. Évitez les noms trop génériques comme test ou temp.

6. Branches distantes

Les branches distantes (remote-tracking branches) sont des références locales qui reflètent l'état des branches sur le dépôt distant (origin). Elles ont le format origin/nom-branche.

Récupérer les changements distants

# Fetch : télécharger les changements SANS merger
git fetch origin

# Fetch d'une branche spécifique
git fetch origin feature/login

# Pull : fetch + merge automatique
git pull origin main

# Pull en rebase (historique linéaire)
git pull --rebase origin main

Pousser une branche

# Pousser et créer le tracking automatique
git push -u origin feature/login

# Une fois le tracking configuré
git push

# Pousser sur une branche distante différente
git push origin feature/login:feature/login-v2

Différence fetch vs pull

CommandeCe qui se passeModifie votre Working Dir
git fetch origin Télécharge les commits distants dans origin/main, etc. Non — sûr à tout moment
git pull origin main Fetch + merge de origin/main dans la branche courante Oui — peut créer des conflits

Branches de tracking

# Voir le tracking de toutes les branches
git branch -vv

# Exemple de sortie :
* feature/login   a3f8c1d [origin/feature/login: ahead 2] feat: ajouter form
  main            7b2e4a9 [origin/main] feat: page accueil

# "ahead 2" = 2 commits locaux non poussés
# "behind 3" = 3 commits distants non récupérés

Récupérer une branche distante en local

# Créer une branche locale qui track la branche distante
git switch -c feature/login origin/feature/login

# Raccourci (Git 2.23+)
git switch feature/login

# Ancienne syntaxe
git checkout --track origin/feature/login

Workflow typique avec remote

# 1. Créer et basculer sur une nouvelle branche
git switch -c feature/mon-widget

# 2. Développer (add + commit)
git add .
git commit -m "feat: ajouter widget météo"

# 3. Pousser et ouvrir une Pull Request
git push -u origin feature/mon-widget

# 4. Après merge de la PR, nettoyer
git switch main
git pull origin main
git branch -d feature/mon-widget
git push origin --delete feature/mon-widget
GitHub Flow (recommandé) : 1 branche par feature → Pull Request → Review → Merge dans main → Déploiement. Simple, efficace pour les équipes agiles.