Si vous travaillez dans le DevOps, vous serez sans doute amené à utiliser de nombreux outils comme Docker, Kubernetes et Git. Ces outils font tous partie des essentiels pour mener à bien un travail de développement collaboratif. Il est donc essentiel de les connaître et les maîtriser. Aujourd’hui, nous allons parler du logiciel de versionning Git et plus précisément de la commande git merge branch. Cet article fait suite aux autres articles sur Git qui sont déjà sur notre blog. Nous vous invitons donc à jeter un œil sur ces articles, mais surtout sur notre article très complet sur Git, car cela vous aidera à comprendre ce qui suit.

L’une des fonctionnalités les plus puissantes de Git est la possibilité de pouvoir reconstituer un historique forké. La commande git merge permet de fusionner différentes branches créées grâce à la commande git branch. Elle est également utilisée avec la commande git checkout pour supprimer une branche obsolète.

Dans cet article, nous allons découvrir le fonctionnement de la commande git merge et comment fusionner les lignes de développement que l’on appelle des branches.

Fonctionnement de la commande git merge branch

Dans la plupart du temps, elle est utilisée pour fusionner deux branches. Mais concrètement, lors de son exécution, la commande git merge récupère différentes séquences de commits puis les unifie pour former un historique unique.

Pour effectuer une fusion, git merge prend deux pointeurs de différents commits. Ensuite, elle cherchera un commit de base commune aux deux autres. Une fois ce commit trouver, la commande va alors créer une nouvelle branche dans laquelle elle combinera les changements de ces différents commit.

Imaginez que vous ayez une nouvelle fonctionnalité de branche et que vous souhaitez faire un merge, donc une fusion, de cette branche de fonctionnalité dans la branche principale (main).

main

Quand la commande git merge se lance, Git détermine systématiquement l’algorithme de merge et va merger la branche de fonctionnalité dans la branche principale.

git-merge-branch

Dans ce processus de fusion, Git va merger automatiquement les différents historiques à votre place. Cependant, si Git trouve des données différentes dans les deux historiques, la fusion ne sera pas effectuée automatiquement, mais nécessite l’intervention de l’utilisateur.

Que signifie exactement fusionner une branche Git ?

Lorsque vous lancez une fusion dans Git, les différentes étapes de modification de votre code sont rassemblées dans une seule chronologie séquentielle. Pour faire une fusion, il y a différentes étapes à suivre pour que la fusion soit faite sans bug.

Confirmer la branche cible

Tout d’abord, il faut lancer la commande git status. Cela permet de s’assurer que le HEAD pointe bien vers la bonne branche. Vous pouvez aussi vous rendre directement dans la branche cible grâce à la commande git checkout.

Mettre à jour les branches

Ensuite, on doit mettre à jour la branche cible afin d’avoir les derniers changements distants. Pour faire cela, il faut exécuter la commande git fetch. Et une fois cette étape faite, il faut s’assurer que la branche principale soit à jour grâce à la commande git pull.

Fusionner

Vous pouvez enfin fusionner après avoir fini avec les étapes de préparation à la fusion évoquée ci-dessus. C’est là qu’il faut lancer la commande git merge.

Le fast forward merge

Quand le chemin existant entre la branche actuelle et la branche cible est linéaire, il peut y avoir un fast-forward merge. Avec cette fonctionnalité, au lieu de fusionner directement les branches, Git va plutôt déplacer la pointe de la branche actuelle vers celle de la branche cible afin d’intégrer les historiques.  Cette opération est faisable, car les commits accessibles depuis la branche actuelle sont aussi accessibles depuis la branche cible.

Mais alors, c’est quoi fast-forward ?

Pour mieux le comprendre, supposons que nous avons une personne nommée Patrick qui modifie une branche. Il crée un commit A et ensuite il effectue une autre modification et crée un commit B. Automatiquement, Git effectuera un “Fast-Forward”, ce qui veut dire qu’il fait pointer la branche qui auparavant pointait vers le commit A vers le commit B. On peut schématiser un Fast-Forward de la branche Some Feature dans la branche principale comme suit :

fast-forward-merge

Il faut noter que le Fast-Forward n’est possible que si les branches sont convergentes. Quand le chemin vers la branche cible n’est pas linéaire, Git passe par une autre option qui consiste à fusionner les branches avec un merge à trois branches.

Pour lier deux historiques, les merges à trois branches passent par un commit dédié à cet effet.

fusioon-a-trois

Beaucoup de développeurs préfèrent utiliser le Fast-Forward pour fusionner des branches. En effet, cela permet d’éviter les petites erreurs tout en réservant la méthode de merge à trois branches pour l’implémentation de fonctionnalités utilisée à plus long terme.

Considérons le code ci-dessous qui crée une nouvelle branche. Ensuite, il ajoute deux commits et pour finir, il intègre la branche dans la ligne principale avec un Fast-Forward merge.

# Démarrer une nouvelle fonctionnalité
git checkout -b nouvelle-fonctionnalité main
# Éditer quelques fichiers
git add 
git commit -m "Démarrer une fonctionnalité"
# Éditer quelques fichiers
git add 
git commit -m "Finir une fonctionnalité"
# Fusionner dans la branche new-feature
git checkout main
git merge nouvelle-fonctionnalité
git branch -d nouvelle-fonctionnalité

Il s’agit ici d’un flux de données de travail commun pour les branches utilisées momentanément. Elle est donc utilisée lors d’un développement isolé plutôt que comme un outil qui peut aider à bien structurer les fonctionnalités utilisées à long terme.

Remarque : la branche nouvelle-fonctionnalité est accessible depuis la branche principale. Par conséquent, Git ne va pas réagir à la commande git branch -d.

Si vous souhaitez archiver vos commits lors d’un Fast-forward il faut ajouter l’option – -no -ff à la commande git merge : 

git merge - -no -ff

Cette commande permet de lancer une fusion de la branche spécifiée dans la branche courante tout en générant un commit de fusion. Cette manière de procéder est très utile pour documenter toutes les fusions qui vont se produire dans le dépôt.

Merge a trois sources

L’exemple ci-dessous est similaire à celui que l’on a vu précédemment : 

# Commencez une nouvelle fonctionnalité
git checkout -b nouvelle fonctionnalité main
# Éditez quelques fichiers
git add 
git commit -m "Démarrer une fonctionnalité"
# Éditer quelques fichiers
git add 
git commit -m "Finir une fonctionnalité"
# Développer la branche principale
git checkout main
# Éditer quelques fichiers
git add 
git commit -m "Faire des changements super-stables à main"
# Fusionner dans la branche new-feature
git merge new-feature
git branch -d new-feature

Ici, Git n’a pas la possibilité de faire un Fast-Forward, parce qu’en voulant déplacer la branche main vers nouvelle-fonctionnalité, il y aura un backtracking.

Pour la plupart des workflows, nouvelle-fonctionnalité est considérée comme une grande fonctionnalité. De ce fait, son développement demande plus de temps, ce qui justifierait l’apparition de nouveaux commits sur main entre-temps. Mais si une branche de fonctionnalité est petite, il faut simplement effectuer un rebase sur la branche principale et faire aussi un Fast-forward merge. En faisant cela, l’historique du projet ne sera pas submergé par des commits.

Résolution de conflits dans git merge branch

Lorsque l’on effectue la fusion des branches et que ces dernières doivent modifier la même partie du fichier, Git ne pourra pas savoir la version à utiliser. En cas de conflit, il faudrait le résoudre manuellement, car Git va s’arrêter avant le commit de merge.    

Le plus gros avantage des fusions dans Git est qu’on utilise le workflow d’édition, d’indexation et de commit pour trouver de solution de conflits lors de la fusion. 

Toutefois, en cas de conflit, il faut lancer la commande git status. Cela affichera les fichiers qui sont en conflit. Si, par exemple, les deux branches modifient la même section de hello.py ce message s’affichera :

On branch main
Unmerged paths:
(use "git add/rm ..." as appropriate to mark resolution)
both modified: hello.py

Presentation des conflits

Au cours de la fusion, si Git rencontre un conflit, il va indexer les contenus des fichiers affectés avec les signes suivants : <<<<<<<, ======= et >>>>>>>. De ce fait, il est vraiment nécessaire d’effectuer une petite vérification lors d’une fusion. Cela permet de savoir s’il y a des conflits à résoudre.

here is some content not affected by the conflict
<<<<<<<main>>>>>>> feature branch;

Le contenu situé avant le marqueur ======= désigne la branche cible et celui d’après représente la branche fusionnée. Grâce aux marqueurs, vous pouvez identifier les parties en conflit et faire le nécessaire pour résoudre le problème.

Une fois le problème résolu, vous pouvez le signaler à Git en lançant la commande git add.

Pour conclure, effectuer la fusion des branches est un processus essentiel surtout quand on travaille avec Git. Il existe deux grands types de fusion dans Git : le Fast-Forward merge et le merge a trois branches. Lors du processus de fusion, Git peut directement fusionner les commits, sauf en cas de conflits.

Voilà, nous sommes à la fin de cet article. Si vous êtes arrivé jusque-là, vous aurez compris l’intérêt de comprendre le fonctionnement de la commande git merge branch. Ainsi, vous pourriez faire face aux éventuels soucis se présentant lors de la fusion.

Si vous souhaitez continuer votre lecture, nous vous invitons à parcourir la section DataOps/DevOps de notre blog. Vous y trouverez d’autres articles sur Git en plus des autres articles sur le DataOps et le DevOps. Nous vous offrons également cette formation sur le développement d’applications Spark avec Scala que vous pouvez télécharger gratuitement.


Juvénal JVC

Juvénal est spécialisé depuis 2011 dans la valorisation à large échelle des données. Son but est d'aider les professionnels de la data à développer les compétences indispensables pour réussir dans le Big Data. Il travaille actuellement comme Lead Data Engineer auprès des grands comptes. Lorsqu'il n'est pas en voyage, Juvénal rédige des livres ou est en train de préparer la sortie d'un de  ses livres. Vous pouvez télécharger un extrait de son dernier livre en date ici : https://www.data-transitionnumerique.com/extrait-ecosystme-hadoop/

>