Merge vs. Rebase : le grand débat
Ah, merge contre rebase. Le duel éternel, responsable d’innombrables guerres de couloir. Les deux résolvent le même problème : faire entrer des changements d’une branche dans une autre. Mais ils le font très différemment, et votre choix dit beaucoup de votre philosophie du contrôle de version.
Allons droit au but. L’un est simple mais produit vite un historique tordu. L’autre demande un poil plus de discipline mais génère un log net et lisible.
Merge
Le merge est souvent vu comme l’option « facile » et « sûre ». Il prend les commits nouveaux de main et les « colle » dans votre branche de fonctionnalité via un commit de merge. En cas de conflits, vous les résolvez une fois, à la fin.
Simple, non ? Sauf que si vous répétez ça pour rester à jour… votre historique devient vite un plat de spaghetti, rempli de « boucles de merge » illisibles.
Et si vous laissez passer ça jusqu’à main, vous importez les assiettes de nouilles de tout le monde dans l’historique. Bon courage pour l’archéologie dans six mois.
Rebase
Le rebase, au début, ressemble à de la magie noire. Vous lancez un rebase, vous vous prenez des conflits sur du code oublié depuis deux semaines… et pourtant tout est normal.
Au lieu de créer un commit de merge, le rebase « rembobine » vos commits (il enlève vos commits), avance votre branche à la pointe de main, puis rejoue vos commits l’un après l’autre par‑dessus.
Supposons trois commits sur votre branche quand main a avancé :
Le rebase les rejoue, un… par… un :
Résultat : un historique parfaitement linéaire. Le piège : en cas de conflits, vous devrez les résoudre à chaque commit rejoué, dans l’état de votre code à chaque étape - c’est déroutant au début.
Le secret pour un rebase facile
Ayez un seul commit à rebaser : soit en ne commitant qu’une fois et en amendement, soit en écrasant vos commits en un seul avant de tirer main.
Vous gardez le meilleur des deux mondes : un seul conflit à gérer (comme merge), mais un historique net (comme rebase).
Mon avis : squash‑then‑rebase
Soyons clairs : je suis un grand fan du squash‑then‑rebase. Aussi simple que merge à l’usage, mais votre branche reste nette et lisible. Et ça reflète exactement ce que deviendra main après merge en squash.
« Mais on perd l’historique ! »
Oui. Et c’est volontaire. Dans nos Do & Don’t, on a déjà acté :
- Branches petites et courtes
- Merge en squash
- Suppression de la branche après merge
Ces branches sont jetables. Leur « historique de sauvegarde » devient du bruit une fois la PR mergée. Ce qui compte, c’est le commit propre qui atterrira sur main. Quelle meilleure préparation que d’avoir déjà un seul commit propre posé sur main dans votre branche ?
« Mais il faut force‑push, c’est dangereux ! »
Dangereux… si vous ne savez pas ce que vous faites, ou si vous poussez en force sur une branche partagée et durable comme main. Sur votre branche de fonctionnalité (votre bac à sable), c’est parfaitement acceptable.
Et si vous collaborez à plusieurs, utilisez git push --force-with-lease --force-if-includes :
--force-with-leasebloque si le remote a évolué sans vous--force-if-includesbloque s’il y a un commit distant que vous n’avez pas localement
Bref, vous n’écrasez pas le travail des autres sans le voir venir. Et surtout : on communique. « Je rebase maintenant », et tout se passe bien.
Au final, à vous de choisir. Mais puisque votre travail sera de toute façon écrasé en un seul commit sur main, autant garder votre branche propre dès le départ. Ça évite d’assaisonner main avec les nouilles des uns et des autres. 😉