Fusionner ou intégrer — est l’action de combiner deux branches dans Git, réunissant les modifications d’une branche à une autre. Dans le développement moderne, le merge est la méthode standard pour intégrer une branche de fonctionnalité dans la branche principale du projet. Selon GitHub Octoverse 2024, plus de 15 millions de merges sont effectués quotidiennement. Merge est un mécanisme clé du travail collaboratif, permettant de combiner les efforts de plusieurs développeurs en un seul produit.
Points Clés
Le merge dans Git est l’opération de combinaison de deux ou plusieurs historiques de développement en un seul. Lorsqu’un développeur fusionne une branche, Git trouve automatiquement l’ancêtre commun (base commit) et crée un nouveau commit de fusion qui inclut les modifications des deux branches. Three-way merge est l’algorithme standard qui compare trois états : l’ancêtre commun, la première branche et la deuxième branche.
Le processus de merge commence par la commande git merge. Git détermine le point de divergence des branches et applique séquentiellement les modifications de la branche source sur la branche cible. Si les modifications ne sont pas en conflit, Git effectue un fast-forward ou crée un merge commit selon la configuration. Fast-forward est un scénario où la branche cible se déplace simplement vers les commits de la branche source.
# Basculer vers la branche cible et fusionner
git checkout main
git merge feature/payment-module
# Fusionner avec no-fast-forward explicite
git merge --no-ff feature/payment-module
# Abandonner le merge si les conflits sont trop complexes
git merge --abort
Le flag --no-ff (no fast-forward) force la création d’un merge commit même lorsqu’un fast-forward est possible. Cela préserve l’information que les modifications ont été effectuées dans une branche séparée. De nombreuses équipes préfèrent cette approche pour maintenir explicitement l’historique de branchement.
Git dispose de trois stratégies principales de fusion de branches, chacune adaptée à un scénario spécifique. Le choix de la stratégie dépend de la culture de l’équipe et des exigences de propreté de l’historique du projet.
| Stratégie | Résultat | Quand l’utiliser |
|---|---|---|
| Standard merge | merge commit + historique complet | équipes qui valorisent l’historique complet |
| Squash merge | un commit, historique compressé | branches de fonctionnalité avec de nombreux petits commits |
| Rebase merge | historique linéaire, sans merge commit | branches de fonctionnalité personnelles, avant de créer un PR |
Standard merge crée un merge commit avec deux parents. L’historique complet est préservé, mais le graphe de branchement devient plus complexe. Squash merge combine tous les commits d’une branche de fonctionnalité en un seul et l’applique sur la branche cible — l’historique devient linéaire et propre, mais les informations sur les étapes intermédiaires sont perdues.
Rebase, bien que n’étant pas une fusion complète, atteint le même résultat — les modifications d’une branche sont déplacées sur une autre. La différence est que l’historique est réécrit : les commits de la branche de fonctionnalité sont recréés sur le dernier commit de la branche cible. Cela donne un historique parfaitement linéaire, mais nécessite un force push lors de l’envoi.
Un conflit de merge survient lorsque les mêmes lignes d’un fichier sont modifiées dans deux branches. Git ne peut pas déterminer automatiquement quelle version conserver et nécessite l’intervention du développeur. Les conflits sont affichés dans les fichiers à l’aide de marqueurs spéciaux : <<<<<<<, =======, >>>>>>>.
Le processus de résolution de conflit comprend plusieurs étapes. D’abord, le développeur ouvre le fichier en conflit et sélectionne manuellement les modifications nécessaires. Il est important non seulement de choisir une version, mais de comprendre la logique des deux modifications et de prendre une décision correcte. Après avoir édité le fichier, les marqueurs de conflit sont supprimés et les modifications sont ajoutées à la staging area via git add.
# Afficher la liste des fichiers en conflit
git status
# Démarrer mergetool (ex. : VS Code, IntelliJ)
git mergetool
# Après avoir résolu tous les conflits
git add .
git merge --continue
# Ou abandonner complètement le merge
git merge --abort
L’utilisation d’outils visuels de merge accélère considérablement la résolution des conflits. VS Code, IntelliJ IDEA et GitKraken fournissent des interfaces à trois panneaux : branche actuelle, branche entrante et résultat. L’outil git mergetool ouvre automatiquement l’éditeur configuré pour chaque fichier en conflit.
La meilleure façon d’éviter les conflits complexes est la synchronisation régulière de la branche de fonctionnalité avec la branche principale. Si un développeur fusionne main dans sa branche une fois par jour, les conflits seront petits et facilement résolubles. Accumuler les modifications pendant une semaine garantit des conflits complexes avec un risque élevé d’erreurs.
Rebase et merge sont deux façons de combiner des modifications, et le choix entre eux suscite souvent des débats dans les équipes. Rebase déplace les commits d’une branche sur une autre, réécrivant l’historique. Merge crée un nouveau commit de fusion, préservant l’historique de branchement. Chaque approche a ses avantages et ses limites.
Rebase est approprié lorsqu’un développeur travaille sur sa branche de fonctionnalité locale et souhaite un historique linéaire propre avant de créer un Pull Request. Après le rebase, tous les commits sont organisés séquentiellement sans commits de merge inutiles. Cependant, rebase nécessite un force push et n’est pas applicable aux branches sur lesquelles plusieurs personnes travaillent simultanément.
La règle d’or de Git : n’utilisez pas rebase sur des commits qui ont déjà été poussés vers le dépôt partagé. Cela garantit que l’historique dans la branche partagée reste inchangé et que les autres développeurs ne rencontreront pas de commits en double ou perdus. Pour intégrer une branche de fonctionnalité dans la branche principale, utilisez merge via Pull Request.
Un processus de merge approprié est le fondement d’un développement stable. Dans le travail d’équipe moderne, la fusion ne se fait pas via la console, mais via Pull Request sur GitHub ou Merge Request dans GitLab. Un PR passe par une revue de code, des vérifications automatiques CI et seulement ensuite est fusionné dans la branche principale.
La première pratique — ne fusionner qu’après la réussite de toutes les vérifications. Le pipeline CI doit compiler le projet, exécuter les tests et vérifier la qualité du code. Si au moins une vérification échoue, le merge est bloqué. Les plateformes modernes (GitHub, GitLab) ont une protection intégrée : les branch protection rules bloquent automatiquement le merge en cas d’échec du CI.
La deuxième pratique — ne jamais fusionner du code cassé. Avant le merge, le développeur doit s’assurer que ses modifications ne cassent pas la compilation et ne régressent pas les fonctionnalités existantes. Pour cela, il existe des tests automatiques et la revue de code.
La troisième pratique — nettoyer les branches de fonctionnalité après le merge. Une branche qui a déjà été fusionnée doit être supprimée. Cela évite la confusion et l’encombrement du dépôt. GitHub propose automatiquement de supprimer la branche après la fusion d’un PR, et les paramètres du dépôt peuvent être configurés pour une suppression automatique.
Questions Fréquentes
Un merge est la combinaison de deux branches Git en une seule. Les modifications d’une branche sont transférées à une autre via une fusion à trois voies (three-way merge). Le résultat est enregistré dans un nouveau commit de fusion qui a deux commits parents. Merge commit préserve les informations sur les branches qui ont été fusionnées.
Merge crée un nouveau commit de fusion, préservant l’historique de branchement. Rebase réécrit l’historique en déplaçant les commits sur une autre branche sans créer de merge commit. Rebase donne un historique linéaire mais nécessite un force push. Merge est plus sûr pour les branches partagées, rebase est meilleur pour les branches personnelles.
Ouvrez le fichier en conflit, trouvez les marqueurs <<<<<<<, ======= et >>>>>>>, sélectionnez les modifications nécessaires et supprimez les marqueurs. Ajoutez le fichier via git add et terminez le merge avec git merge --continue. Utilisez git mergetool pour une résolution visuelle dans VS Code ou IntelliJ IDEA.
Pull Request (ou Merge Request) est obligatoire lors de la fusion d’une branche de fonctionnalité dans la branche principale du projet. Un PR passe par une revue de code des collègues et des vérifications automatiques CI. C’est le standard du développement moderne. Le push direct dans la branche principale est interdit dans la plupart des projets.
Squash merge combine tous les commits d’une branche de fonctionnalité en un seul avant la fusion. Cela donne un historique propre de la branche principale sans commits de brouillon intermédiaires. Utilisez squash merge lorsqu’une branche de fonctionnalité contient de nombreux commits utilitaires (wip, fixes) et qu’il n’est pas nécessaire de conserver toutes les étapes intermédiaires dans l’historique.
Résumé
Nous développerons une application mobile clé en main
IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.
Lisez aussi