W3docs

stratégies de fusion

Apprenez les stratégies de fusion Git — ort, recursive, resolve, octopus, ours et subtree — ainsi que les fusions fast-forward, squash et explicites, avec des exemples.

conflits de fusion

Stratégies de fusion Git

Lorsque votre travail sur une branche est terminé et prêt à être intégré à la ligne principale de développement, Git doit décider comment assembler les deux historiques. L'algorithme qu'il utilise pour cela s'appelle une stratégie de fusion.

Une stratégie de fusion prend deux (ou plusieurs) extrémités de branches et produit un résultat unique. La plupart du temps, vous ne nommez jamais explicitement une stratégie — la commande git merge choisit une valeur par défaut sensée en fonction du nombre de branches que vous fusionnez et du fait que leurs historiques ont divergé ou non. Lorsque vous avez besoin de contrôle, passez -s <stratégie> (et éventuellement -X <option-de-stratégie> pour un réglage fin) :

git merge -s recursive feature

Cette page couvre deux idées liées qui sont faciles à confondre :

  • Stratégies de fusion (-s) : l'algorithme qui calcule l'arbre fusionné — ort, recursive, resolve, octopus, ours, subtree.
  • Types de fusion : la nature du résultat obtenu — un commit de fusion explicite, un fast-forward, ou un squash.

Vous n'avez presque jamais besoin de choisir une stratégie manuellement. Les valeurs par défaut sont correctes pour la grande majorité des fusions ; recourez à -s ou -X uniquement lorsque vous rencontrez un problème spécifique qu'elles permettent de résoudre.

Algorithmes de stratégie de fusion

ort (par défaut)

git merge -s ort feature

ortOstensibly Recursive's Twin ») est la stratégie de fusion par défaut pour deux têtes depuis Git 2.34 (2021). Il s'agit d'une réécriture plus rapide et plus correcte de l'ancienne stratégie recursive, produisant le même type de résultat : une fusion à 3 voies qui gère les renommages et fusionne récursivement plusieurs ancêtres communs en un seul ancêtre virtuel.

Étant donné qu'il s'agit de la valeur par défaut, vous obtenez ort automatiquement lorsque vous exécutez une fusion simple :

git checkout main
git merge feature

recursive

git merge -s recursive feature

La stratégie originale à 3 voies pour fusionner deux branches, et la valeur par défaut avant Git 2.34. Elle peut détecter et suivre les renommages, mais ne peut pas utiliser les copies de fichiers détectées. Vous n'avez pratiquement jamais besoin de la demander par son nom maintenant — ort la supplante — mais elle reste disponible pour des raisons de compatibilité.

resolve

git merge -s resolve feature

resolve effectue une fusion à 3 voies unique entre exactement deux têtes (la branche courante et celle que vous nommez). Elle n'essaie pas d'être intelligente avec plusieurs bases de fusion, ce qui la rend rapide et prévisible, mais elle peut mal fusionner dans un historique en « criss-cross » où deux branches ont été fusionnées l'une dans l'autre précédemment. Utilisez-la uniquement lorsque la fusion recursive/ort produit un résultat que vous souhaitez vérifier avec un algorithme plus simple.

octopus

git merge -s octopus topic-a topic-b topic-c

octopus est la stratégie par défaut lorsque vous fusionnez plus de deux branches à la fois. Elle regroupe plusieurs extrémités de branches en un seul commit de fusion, ce qui est pratique pour réunir un ensemble de branches de sujet indépendantes. Elle refuse délibérément toute fusion qui nécessiterait une résolution manuelle des conflits — les fusions octopus sont censées être propres ; s'il y a un conflit, vous devez fusionner les branches individuellement à la place.

ours

git merge -s ours obsolete-branch

La stratégie ours enregistre un commit de fusion qui a l'autre branche comme parent, mais conserve l'arbre de votre branche courante complètement inchangé — chaque modification de l'autre branche est ignorée. L'utilisation typique est de marquer une branche comme « fusionnée » dans l'historique (afin que les futures fusions en soient informées) tout en ignorant son contenu réel, par exemple lors de la mise à la retraite d'une branche de longue durée dont le travail n'est plus souhaité.

Avertissement

Ne confondez pas la stratégie ours (-s ours, qui ignore entièrement le contenu de l'autre branche) avec l'option de stratégie ours (-X ours, qui conserve votre côté uniquement pour les lignes qui sont réellement en conflit). Elles se comportent très différemment.

subtree

git merge -s subtree project-b

subtree est une variante de l'algorithme recursive/ort pour le cas où un arbre est un sous-répertoire (un « sous-arbre ») de l'autre. Avant de fusionner, Git déplace les chemins d'un arbre de façon à ce que les deux s'alignent, puis fusionne normalement. C'est le mécanisme permettant d'incorporer un projet dans un sous-dossier d'un autre. Pour le travail quotidien avec les sous-arbres, la commande de niveau supérieur git subtree est généralement plus simple.

Types de fusion : à quoi ressemble le résultat

La stratégie décide comment les arbres sont combinés ; le type de fusion décrit la forme de l'historique qui en résulte.

Fusion fast-forward

Lorsque la branche dans laquelle vous fusionnez n'a pas bougé depuis la création de l'autre branche, il n'y a rien à combiner — Git peut simplement avancer le pointeur de branche jusqu'au dernier commit. Aucun nouveau commit n'est créé et l'historique reste parfaitement linéaire. C'est le comportement par défaut de Git chaque fois que c'est possible :

git checkout main
git merge feature
# Output (when main is an ancestor of feature):
# Updating a1b2c3d..d4e5f6a
# Fast-forward
#  app.js | 3 +++
#  1 file changed, 3 insertions(+)

Pour conserver un enregistrement explicite de la fusion même lorsqu'un fast-forward est possible, forcez un commit de fusion avec --no-ff :

git merge --no-ff feature

Commit de fusion explicite (à 3 voies)

Lorsque les deux branches ont de nouveaux commits — leurs historiques ont divergé — Git crée un tout nouveau commit de fusion avec deux parents. Il est dit « explicite » car le commit est visible dans l'historique et enregistre exactement où et quand les branches se sont rejointes :

git checkout main
git merge feature
# Output (when histories diverged):
# Merge made by the 'ort' strategy.
#  app.js | 5 +++++
#  1 file changed, 5 insertions(+)

Si les deux branches ont modifié les mêmes lignes, la fusion s'arrête avec un conflit que vous devez résoudre manuellement — voir conflits de fusion.

Fusion squash

Une fusion squash réduit tous les commits de la branche source en un seul nouveau commit sur la branche courante. Elle ne crée pas de commit de fusion et n'enregistre pas la branche source comme parent, de sorte que les commits individuels de la branche source n'apparaissent jamais dans l'historique cible :

git checkout main
git merge --squash feature
# Changes are staged but NOT committed yet:
git commit -m "Add feature X"

Cela permet de garder l'historique de la branche principale ordonné — un commit par fonctionnalité — au prix de la perte du journal de commits détaillé de la branche de fonctionnalité. C'est une politique populaire pour les pull requests. Pour réécrire des commits au sein d'une branche, voir rebase interactif.

Options de stratégie (-X)

Les stratégies ort/recursive acceptent des options supplémentaires via l'indicateur -X (notez le X majuscule, distinct de -s). Par exemple, pour résoudre automatiquement les conflits en faveur de votre côté :

git merge -X ours feature

Les options disponibles sont :

OptionEffet
oursRésout automatiquement les blocs en conflit en favorisant notre côté. Les modifications non conflictuelles de l'autre arbre sont quand même fusionnées. (Contrairement à -s ours, qui ignore entièrement l'autre côté.)
theirsL'opposé de ours : résout automatiquement les conflits en faveur de l'autre arbre. Il n'existe pas de stratégie theirs séparée, seulement cette option.
patiencePasse plus de temps à faire correspondre les lignes afin d'éviter les mauvaises fusions causées par des lignes correspondantes non importantes.
diff-algorithm=<algo>Indique à la fusion d'utiliser un algorithme de diff différent (par ex. histogram, minimal, patience).
ignore-space-change / ignore-all-spaceIgnore les différences portant uniquement sur les espaces lors de la détection des conflits. Les modifications d'espaces mélangées à de vraies modifications ne sont pas ignorées.
renormalizeEffectue un check-out et un check-in virtuels de toutes les étapes du fichier, utile lorsque les filtres de fin de ligne ou smudge/clean ont changé.
no-renormalizeDésactive l'option renormalize.
no-renamesDésactive la détection des renommages lors de la fusion.
find-renames=<n>Active la détection des renommages avec un seuil de similarité de n% (50% par défaut).
subtree=<path>Similaire à la stratégie subtree, mais vous permet de spécifier le préfixe de chemin à déplacer pour aligner les arbres.

Comment choisir

Pour le travail quotidien, vous ne choisissez pas du tout de stratégie — laissez Git utiliser ort, et décidez uniquement du résultat souhaité :

  • Vous voulez l'historique le plus simple et linéaire possible ? Utilisez simplement git merge (les fast-forwards sont automatiques).
  • Vous voulez que chaque fusion soit enregistrée comme un commit ? Ajoutez --no-ff.
  • Vous voulez un seul commit propre par fonctionnalité sur main ? Utilisez --squash.
  • Vous rejoignez plusieurs branches de sujet terminées à la fois ? Un simple git merge a b c utilise octopus.

Si vous préférez rejouer vos commits au-dessus de la branche cible plutôt que de fusionner, consultez git rebase. Pour récupérer un seul commit d'une autre branche, utilisez git cherry-pick.

Pratique

Pratique
Quelles sont les différentes stratégies de fusion dans Git et leurs caractéristiques ?
Quelles sont les différentes stratégies de fusion dans Git et leurs caractéristiques ?
Was this page helpful?