Utiliser des branches

Options et exemples de stratégie de merge Git

Lorsqu'une tâche est terminée, testée et prête à être de nouveau mergée dans la ligne de développement principale, votre équipe doit choisir la politique à adopter. Quelles sont les options de stratégie de merge possibles ? Dans cet article, nous étudierons les possibilités et expliquerons brièvement la méthode adoptée par Atlassian. À la fin, vous devriez disposer des outils nécessaires pour choisir les options les plus adaptées à votre équipe.

Stratégies de merge Git

Un merge se produit lorsque deux branches sont associées. Git prend deux pointeurs de commit (ou plus) et essaie de trouver un commit de base commun aux deux. Git dispose de plusieurs méthodes différentes pour rechercher un commit de base, appelées « stratégies de merge ». Dès que Git trouve un commit de base commun, il crée un « commit de merge » qui combine les changements des commits de merge spécifiés. Techniquement, le terme « commit de merge » désigne un commit normal, qui présente deux commits parent.

git merge sélectionne automatiquement une stratégie de merge, sauf indication contraire. Les commandes git merge et git pull peuvent être transmises avec l'option -s (stratégie). Cette option -s peut être ajoutée avec le nom de la stratégie de merge souhaitée. Sauf indication contraire, Git sélectionne la stratégie de merge la plus adaptée en fonction des branches fournies. Voici une liste des stratégies de merge disponibles.

Stratégie « recursive »

git merge -s recursive branch1 branch2

Cette stratégie fonctionne sur deux têtes. « recursive » est la stratégie de merge par défaut lorsque vous faites un pull d'une branche ou la mergez. De plus, elle peut identifier et gérer les merges impliquant des changements de nom, mais ne peut actuellement pas utiliser les copies détectées. Il s'agit de la stratégie de merge par défaut lorsque vous faites un pull d'une branche ou la mergez.

Résolution

git merge -s resolve branch1 branch2

Elle peut uniquement résoudre deux têtes à l'aide d'un algorithme de merge à trois branches. Elle s'efforce de bien détecter les quelques ambiguïtés de merge, et est généralement considérée comme sûre et rapide.

Stratégie « octopus »

git merge -s octopus branch1 branch2 branch3 branchN

La stratégie de merge par défaut pour plus de deux têtes. Lorsque plusieurs branches sont transmises, « octopus » est automatiquement utilisée. Si un merge présente des conflits qui nécessitent une résolution manuelle, « octopus » refusera la tentative de merge. Elle est principalement employée pour regrouper des têtes de branche aux fonctionnalités similaires.

Stratégie « ours »

git merge -s ours branch1 branch2 branchN

La stratégie « ours » fonctionne sur N branches. Le résultat du merge sortant est toujours celui de l'élément HEAD de la branche actuelle. Le terme « ours » implique que la préférence ignore dans les faits tous les changements provenant des autres branches. Il est utilisé pour combiner l'historique de branches aux fonctionnalités similaires.

Stratégie « subtree »

git merge -s subtree branchA branchB

C'est une extension de la stratégie « recursive ». Lors du merge de A et B, si B est une sous-arborescence enfant de A, B est d'abord mise à jour pour refléter la structure d'arborescence de A. Cette mise à jour est également effectuée sur l'arborescence ancêtre commune à A et B.

Types de stratégies de merge Git

Merges explicites

Les merges explicites constituent le type de merge par défaut. Ils sont dits « explicites », car ils créent un commit de merge. Cette action modifie l'historique des commits et indique explicitement où un merge a été exécuté. Le contenu du commit de merge est également explicite dans la mesure où il montre les commits parent du commit de merge. Certaines équipes évitent les merges explicites, car les commits de merge peuvent ajouter des « interférences » à l'historique du projet.

Merge implicite via un rebase ou un fast-forward merge

Alors que les merges explicites créent un commit de merge, les merges implicites ne le font pas. Un merge implicite prend une série de commits d'une tête de branche spécifiée et les applique au sommet d'une branche cible. Les merges implicites sont déclenchés par des événements de rebase ou des fast-forward merges. Un merge implicite est une sélection ad hoc de commits provenant d'une branche spécifiée.

Merge squash, généralement sans merge explicite

Un squash est un autre type de merge implicite. Il peut se produire au cours d'un rebase interactif. Un merge squash prend les commits d'une branche cible, et les combine ou les squashe en un seul commit. Ce commit est ensuite ajouté à l'élément HEAD de la branche de base du merge. Un squash est couramment utilisé pour conserver un « historique propre » pendant un merge. La branche de merge cible peut présenter un historique détaillé de commits fréquents. Une fois le squash et le merge effectués, l'historique de commit de branches cible devient une « branche de commit » squashée unique. Cette technique est utile avec les workflows Git qui utilisent des branches de fonctionnalité.

Options et exemples de stratégie de merge Git « recursive »

La stratégie « recursive » mentionnée ci-dessus dispose de son propre sous-ensemble d'options opérationnelles supplémentaires.

ours

À ne pas confondre avec la stratégie de merge « ours ». Ce conflit d'options est résolu automatiquement en privilégiant la version « ours ». Les changements introduits par la version « theirs » sont automatiquement intégrés s'ils n'entrent pas en conflit.

theirs

Le contraire de la stratégie « ours ». L'option « theirs » favorise l'arborescence de merge étranger dans la résolution des conflits.

patience

Cette option consacre davantage de temps à éviter les erreurs de merge sur des lignes de correspondance sans importance. Elle doit être privilégiée lorsque les branches à merger sont extrêmement divergentes

diff-algorithim

Cette option permet de spécifier un algorithme de diff explicite. Les algorithmes de diff sont partagés grâce à la commande git diff.

ignore-*

    ignore-space-change
    ignore-all-space
    ignore-space-at-eol
    ignore-cr-at-eol

Un ensemble d'options qui ciblent les caractères d'espacement. Toute ligne qui correspond au sous-ensemble de l'option transmise sera ignorée.

renormalize

Cette option effectue un check-out et un check-in sur les trois arborescences Git, tout en résolvant un merge à trois branches. Elle doit être utilisée pour merger des branches ayant des états checkin et checkout différents.

no-normalize

Désactive l'option « renormalize », ce qui annule la variable de configuration merge.renormalize.

no-renames

Cette option permet d'ignorer les fichiers renommés lors du merge.

find-renames=n

Il s'agit d'un comportement par défaut. Le merge « recursive » honore les renommages de fichiers. Le paramètre n peut être utilisé pour transmettre un seuil de similarité de renommage. La valeur par défaut de n est de 100 %.

subtree

Cette option s'inspire de la stratégie « subtree ». Tandis que la stratégie « subtree » fonctionne sur deux arborescences et modifie leur correspondance sur un ancêtre commun, cette option fonctionne plutôt sur les métadonnées de chemin de l'arborescence pour les faire correspondre.

Notre politique de merge Git

Atlassian préfère nettement utiliser des merges explicites. Pourquoi ? Les merges explicites offrent tout simplement une parfaite traçabilité et un contexte sur les fonctionnalités mergées. Nous recommandons vivement de faire un rebase de nettoyage de l'historique local avant de partager une branche de fonctionnalité pour revue. Cette action ne change en rien la politique, elle l'enrichit.

Prêt à tester la création de branches ?

Essayez ce tutoriel interactif.

Démarrez maintenant