Aller au contenu principal
GitGitHubFormationDevOps

Merge, rebase et résolution de conflits

30 min de lecture Git & GitHub — Chapitre 4

Rebase vs merge, git stash, cherry-pick, stratégies de branching (Git Flow, trunk-based) et tags pour marquer tes versions.

Tu sais créer des branches et les fusionner avec git merge. Mais dans une vraie équipe, ça ne suffit pas. Quand trois devs bossent en parallèle sur le même projet, l’historique Git devient vite un plat de spaghetti illisible. C’est là que merge et rebase entrent en jeu — deux façons de combiner du travail, avec des philosophies opposées. Maîtriser les deux, c’est ce qui sépare le dev qui subit Git de celui qui le contrôle.

Pourquoi merge et rebase sont essentiels

Dans un projet solo, tu peux te permettre un historique chaotique. En entreprise, c’est différent. Quand un incident survient en production à 3h du matin, tu as besoin d’un historique clair pour comprendre quel commit a tout cassé. Un git log lisible, c’est ton meilleur outil de debug.

💡 Tip DevOps : En CI/CD, un historique propre facilite les rollbacks automatisés. Si chaque merge est un commit explicite et chaque feature une ligne claire, ton pipeline peut reverter chirurgicalement sans casser le reste.

Le merge préserve tout le contexte — qui a fait quoi, quand, et comment les branches se sont croisées. Le rebase, lui, réécrit l’histoire pour la rendre linéaire. Les deux sont utiles, mais dans des contextes différents.

Comprendre la différence entre merge et rebase

Imagine deux développeurs : Alice travaille sur feature/auth, Bob sur feature/api. Pendant ce temps, des commits arrivent sur main.

Avec merge, Git crée un “commit de merge” qui relie les deux historiques. Tu vois exactement quand la branche a été fusionnée. L’historique ressemble à un réseau de métro — plusieurs lignes qui se croisent.

Avec rebase, Git “rejoue” tes commits comme s’ils avaient été faits après les derniers changements de main. L’historique devient une ligne droite. Plus propre, mais l’histoire originale est perdue.

Pour visualiser, voici ce qui se passe quand tu rebases ta branche feature sur main :

Avant rebase :
main:    A → B → C → F
                  \
feature:           D → E

Après rebase :
main:    A → B → C → F
                      \
feature:               D' → E'

Les commits D et E sont recréés (D’ et E’) avec de nouveaux hashs. C’est une réécriture d’historique — et c’est là que ça peut devenir dangereux si tu ne fais pas attention.

🧠 À retenir : Merge = autoroute avec échangeurs (on voit toutes les sorties). Rebase = ligne droite (plus lisible, mais on perd les intersections). Les deux arrivent à destination — c’est une question de lisibilité de l’historique.

⚠️ Attention : Ne jamais rebase une branche sur laquelle d’autres personnes travaillent. Le rebase réécrit les hashs des commits. Si un collègue a déjà pullé les anciens commits, vous allez avoir des duplications et des conflits impossibles à démêler.

Commandes essentielles

Le workflow recommandé en équipe combine les deux approches. Tu rebases ta branche perso pour la nettoyer, puis tu merges dans main pour garder la trace.

Voici comment rebaser ta feature sur main avant de la fusionner :

# Met à jour main
git switch main
git pull origin main

# Rebase ta feature sur main
git switch feature/auth
git rebase main

# En cas de conflit : résous, puis continue
git add fichier_resolu.py
git rebase --continue

Le rebase interactif est l’outil le plus puissant pour nettoyer tes commits avant un merge. Il te permet de fusionner, réordonner ou réécrire tes messages de commit :

# Réécrire les 3 derniers commits
git rebase -i HEAD~3

# L'éditeur affiche :
# pick abc1234 feat: ajout route /users
# pick def5678 fix: typo middleware
# pick ghi9012 feat: validation

# Change en :
# pick abc1234 feat: ajout route /users
# fixup def5678 fix: typo middleware
# fixup ghi9012 feat: validation
# → Résultat : un seul commit propre

Une fois ta branche nettoyée, merge dans main avec --no-ff pour créer un commit de merge explicite :

git switch main
git merge --no-ff feature/auth -m "Merge feature/auth: système d'authentification"
git branch -d feature/auth
git push origin main

💡 Tip DevOps : --no-ff (no fast-forward) force la création d’un commit de merge même si Git pourrait faire un fast-forward. C’est essentiel pour garder une trace des features dans l’historique et faciliter les reverts.

Pour les situations d’urgence, deux commandes bonus indispensables. git stash met de côté ton travail en cours sans commiter, et git cherry-pick copie un commit précis d’une branche à l’autre :

# Stash : met de côté ton travail en cours
git stash push -m "WIP: formulaire login"
# ... corrige le bug urgent sur main ...
git stash pop  # Récupère ton travail

# Cherry-pick : copie un commit spécifique
git switch main
git cherry-pick abc1234  # Applique ce fix sans merger toute la branche

Cas concret en entreprise

🔥 Cas réel : Tu travailles dans une équipe de 5 devs sur une app e-commerce. Vendredi 17h, la branche feature/checkout est prête après une semaine de dev. Mais main a bougé — 12 commits de tes collègues sont passés entre-temps.

Voici le workflow que ton équipe applique :

# 1. Tu nettoies tes 8 commits en 3 commits logiques
git rebase -i HEAD~8
# → "feat: panier", "feat: paiement Stripe", "feat: confirmation email"

# 2. Tu rebases sur main pour intégrer les changements récents
git rebase main
# → Conflit sur utils/price.py (ton collègue a modifié le même calcul)
# Tu résous le conflit, puis :
git add utils/price.py
git rebase --continue

# 3. Tu push et ouvres une Pull Request
git push origin feature/checkout --force-with-lease

# 4. Après review, le tech lead merge avec --no-ff
git switch main
git merge --no-ff feature/checkout
git tag -a v2.3.0 -m "Release 2.3.0 - Nouveau checkout"

Le --force-with-lease est plus sûr que --force : il refuse de push si quelqu’un d’autre a poussé des commits entre-temps. C’est le filet de sécurité du rebase.

🧠 À retenir : Le workflow “rebase local → merge public” est le standard dans la majorité des équipes pro. Rebase pour nettoyer, merge pour tracer.

Pièges fréquents et comment les éviter

1. Rebase une branche partagée. C’est LE piège classique. Tu rebases develop, tu push force, et soudain 4 collègues ont des historiques divergents. Règle simple : on ne rebase que ses propres branches.

2. Oublier --force-with-lease après un rebase. Après un rebase, un git push classique sera rejeté (les hashs ont changé). Le réflexe dangereux : git push --force. Le bon réflexe : git push --force-with-lease qui vérifie que personne n’a poussé entre-temps.

3. Paniquer devant un conflit de rebase. Un conflit pendant un rebase peut sembler intimidant parce qu’il se produit commit par commit. Mais tu peux toujours abandonner proprement :

# Abandonner un rebase en cours — retour à l'état d'avant
git rebase --abort

4. Ne jamais nettoyer ses commits. Pousser des commits comme “fix”, “fix2”, “ça marche maintenant”, “oups” pollue l’historique de toute l’équipe. Un rebase -i avant le merge prend 2 minutes et rend le projet maintenable.

⚠️ Attention : Si tu as déjà push ta branche et que tu fais un rebase interactif, tu devras force-push. Assure-toi que personne d’autre ne travaille sur cette branche avant de le faire.

Exercice pratique et points clés

Mets en pratique avec cet exercice complet. Crée un repo, simule un workflow d’équipe, et observe la différence entre merge et rebase :

# Setup
mkdir merge-rebase-lab && cd merge-rebase-lab
git init && echo "# Lab" > README.md
git add . && git commit -m "init"

# Crée une feature avec 3 commits
git switch -c feature/api
echo "v1" > api.py && git add . && git commit -m "feat: endpoint v1"
echo "v2" > api.py && git add . && git commit -m "fix: correction endpoint"
echo "v3" > api.py && git add . && git commit -m "feat: validation ajoutée"

# Pendant ce temps, main avance
git switch main
echo "updated" >> README.md && git add . && git commit -m "docs: update readme"

# Nettoie et rebase
git switch feature/api
git rebase -i HEAD~3        # Squash les 3 en 1
git rebase main              # Rebase sur main

# Merge proprement
git switch main
git merge --no-ff feature/api -m "Merge feature/api"
git log --oneline --graph    # Admire l'historique propre

🔥 Cas réel : Compare le résultat de git log --oneline --graph avec et sans rebase. Tu verras immédiatement pourquoi les équipes qui rebasent ont un historique 10x plus lisible.


🧠 À retenir

  • Merge préserve l’historique complet — idéal pour les branches partagées et la traçabilité
  • Rebase linéarise l’historique — parfait pour nettoyer tes branches perso avant un merge
  • Le workflow pro : rebase en local, merge en public avec --no-ff
  • --force-with-lease > --force — toujours
  • En cas de doute pendant un rebase : git rebase --abort et on recommence sereinement
  • Un historique propre, c’est un investissement qui paie à chaque debug, chaque review, chaque rollback

Articles liés