W3docs

git merge

Découvrez la commande git merge, son fonctionnement et la différence entre la fusion fast-forward et la fusion à 3 points.

La commande git merge réunit deux lignes de développement ou plus. Lorsque vous terminez une fonctionnalité sur sa propre branche, git merge prend le travail de cette branche et l'intègre dans la branche sur laquelle vous vous trouvez actuellement, produisant un historique combiné unique.

Cette page explique ce qui se passe lors d'une fusion, la différence entre une fusion fast-forward et une fusion à 3 points, comment forcer un commit de fusion, et comment reconnaître et résoudre un conflit de fusion.

Elle fonctionne en étroite relation avec git branch (pour créer et supprimer des branches), git checkout (pour basculer vers la branche de réception), et git pull (pour mettre à jour avant de fusionner). Si vous préférez un historique linéaire sans commits de fusion, consultez git rebase comme alternative.

Fonctionnement

L'utilisation principale de git merge est de combiner deux branches. Elle sert également à intégrer plusieurs commits d'une branche dans une autre. Dans l'illustration suivante, git merge prend deux extrémités de branches et trouve un commit ancêtre commun entre elles. Le commit de base commun est utilisé pour créer un nouveau commit de fusion qui combine les modifications des deux branches. Nous avons ici deux branches : master et stage. Nous devons fusionner la branche stage dans la branche master.

gitmerge

Les commits de fusion sont uniques car ils ont deux commits parents. Git combine automatiquement les historiques séparés lors de la création d'un nouveau commit de fusion. Cependant, si les deux branches modifient les mêmes lignes, Git ne peut pas les combiner automatiquement, ce qui entraîne un conflit de fusion.

gitmerge1

Processus de fusion

Avant de démarrer le processus de fusion, suivez ces étapes :

  • Assurez-vous d'être sur la bonne branche de réception. Exécutez git checkout <branche de réception> pour y basculer.
  • Mettez à jour la branche cible avec les dernières modifications distantes. Exécutez git pull pour récupérer et intégrer les derniers commits distants.
  • La dernière étape consiste à exécuter git merge <nom de branche>, qui spécifie la branche à fusionner dans la branche de réception.

Fusion fast-forward

Une fusion fast-forward se produit lorsque le chemin entre la branche actuelle et la branche cible est linéaire. La fusion fast-forward combine les historiques, car tous les commits accessibles depuis la branche cible sont disponibles via la branche actuelle. Voici un exemple de fusion fast-forward :

gitmerge2

Lorsque les deux historiques ont divergé, Git utilise la fusion à 3 points comme alternative. La fusion à 3 points utilise un commit dédié pour combiner deux historiques.

gitmerge3

Les fusions fast-forward sont généralement utilisées pour les petites fonctionnalités ou les corrections de bugs, tandis que les fusions à 3 points sont utilisées pour intégrer des fonctionnalités de longue durée. Les exemples suivants utilisent une fusion fast-forward :

git merge

# Start the stage
git checkout -b stage master
# Edit some files
git add <file>
git commit -m "Start with the stage"
# Edit some files
git add <file>
git commit -m "Finish with the stage"
# Merge in the stage branch
git checkout master
git merge stage
git branch -d stage

Nous exécutons git branch -d pour supprimer la branche stage, car stage est maintenant accessible depuis la branche master.

La commande git merge avec l'option --no-ff est utilisée si vous avez besoin d'un commit de fusion lors d'une fusion fast-forward pour fusionner la branche spécifiée dans la branche actuelle, en générant toujours un commit de fusion (même dans le cas d'une fusion fast-forward) :

git merge --no-ff

git merge --no-ff <branch>

Fusion à 3 points

Ce scénario nécessite une fusion à 3 points lorsque la branche master progresse tandis que la branche stage est encore en développement. Cela est utilisé lorsque les membres de l'équipe travaillent simultanément sur une grande fonctionnalité :

the git merge command

# Start the stage
git checkout -b stage master
# Edit some files
git add <file>
git commit -m "Start with the stage"
# Edit some files
git add <file>
git commit -m "Finish with the stage"
# Develop the master branch
git checkout master
# Edit some files
git add <file>
git commit -m "Make some super-stable changes to master"
# Merge in the stage branch
git merge stage
git branch -d stage

Dans l'exemple ci-dessus, stage serait une fonctionnalité plus importante nécessitant beaucoup de temps à développer, c'est pourquoi nous utilisons une fusion à 3 points. Si votre fonctionnalité est petite, il vaut mieux utiliser une fusion fast-forward pour éviter que des commits inutiles n'encombrent l'historique du projet.

Options de fusion utiles

Ces options modifient le comportement de git merge :

OptionCe qu'elle fait
--no-ffCrée toujours un commit de fusion, même lorsqu'une fusion fast-forward est possible. Garde la branche de fonctionnalité visible dans l'historique.
--ff-onlyFusionne uniquement si une fusion fast-forward est possible ; sinon abandonne. Utile dans les scripts pour refuser un commit de fusion.
--squashCombine tous les commits de la branche en un seul ensemble de modifications en zone de transit (vous commitez ensuite manuellement). Pas de commit de fusion ni de second parent.
--abortArrête une fusion en conflit et restaure la branche à son état avant la fusion.
-m "<msg>"Définit directement le message du commit de fusion sans ouvrir un éditeur.

Une fusion squash est pratique lorsqu'une branche de fonctionnalité comporte de nombreux petits commits « work in progress » que vous ne souhaitez pas dans l'historique principal :

git merge --squash

git checkout master
git merge --squash stage
git commit -m "Add stage feature"

Résolution des conflits

Lors de la fusion de deux branches, si la même partie du même fichier est modifiée, des conflits de fusion surviennent car Git ne peut pas déterminer quelle version utiliser. Dans ce cas, Git s'arrête avant de créer le commit de fusion pour vous permettre de résoudre le conflit. Le processus de fusion Git utilise un flux de travail modifier/indexer/commiter pour résoudre les conflits de fusion. Lorsqu'un conflit se produit, l'exécution de git status affiche les fichiers qui doivent être résolus. L'image suivante s'affiche lorsque les mêmes parties du fichier example.txt ont été modifiées :

git status

On branch master
Unmerged paths:
(use "git add/rm ..." as appropriate to mark resolution)
both modified: example.txt

Si vous décidez de ne pas poursuivre la fusion, vous pouvez l'annuler à tout moment en exécutant git merge --abort.

Comment les conflits sont présentés

En cas de conflits, Git modifie le contenu des fichiers affectés avec des marqueurs visuels des deux côtés du contenu en conflit. Les conflits ne peuvent survenir que lors d'une fusion à 3 points — une fusion fast-forward n'entre jamais en conflit, car la branche de réception n'avait pas de nouveaux commits propres à elle susceptibles d'entrer en collision.

Les marqueurs principaux sont <<<<<<<, =======, et >>>>>>>. Ils vous aident à localiser les sections en conflit dans vos fichiers.

git conflicts

here is some content not affected by the conflict
<<<<<<< master
this is conflicted text from master
=======
this is conflicted text from stage branch
>>>>>>> stage

Pour résoudre le conflit, ouvrez le fichier, supprimez les trois lignes de marqueurs (<<<<<<<, =======, >>>>>>>), et modifiez le texte restant pour obtenir la version que vous souhaitez conserver. Exécutez ensuite git add <file> sur le fichier en conflit pour le marquer comme résolu, puis exécutez git commit pour créer le commit de fusion.

Un exemple complet

La session ci-dessous crée deux branches qui modifient la même ligne, les fusionne, rencontre un conflit, le résout et termine la fusion. Vous pouvez coller ces commandes dans n'importe quel répertoire vide pour le reproduire exactement.

reproduce a conflict and resolve it

git init demo && cd demo
echo "line one" > file.txt
git add file.txt
git commit -m "Initial commit"

# Create a branch and change the line there
git checkout -b stage
echo "change from stage" > file.txt
git commit -am "Edit on stage"

# Change the same line on master
git checkout master
echo "change from master" > file.txt
git commit -am "Edit on master"

# Merge stage into master -> conflict
git merge stage
# Auto-merging file.txt
# CONFLICT (content): Merge conflict in file.txt
# Automatic merge failed; fix conflicts and then commit the result.

Après avoir modifié file.txt pour conserver la version souhaitée, finalisez la fusion :

git add file.txt
git commit -m "Merge stage, keep resolved line"
git branch -d stage

Vérifier une fusion

Après la fusion, confirmez le résultat avec git log. Les options --graph et --oneline dessinent la topologie des branches, ce qui permet de repérer facilement un commit de fusion (avec deux parents) :

git log --oneline --graph

Si vous décidez qu'une fusion terminée était une erreur, git reset peut ramener la branche au commit précédant la fusion.

Pratique

Pratique
Quelles sont les principales caractéristiques et processus impliqués dans la commande 'git merge' ?
Quelles sont les principales caractéristiques et processus impliqués dans la commande 'git merge' ?
Was this page helpful?