Close

git merge

Dans Git, le merge permet de reconstituer un historique forké. La commande git merge vous permet de sélectionner les lignes de développement indépendantes créées avec git branch et de les intégrer à une seule branche.

Remarque : toutes les commandes présentées ci-après font un merge dans la branche courante. La branche courante sera mise à jour pour faire état du merge, tandis que la branche cible restera inchangée. À nouveau, cela signifie que la commande git merge est souvent utilisée en association avec git checkout pour sélectionner la branche courante et git branch -dsupprimer la branche cible obsolète.


Fonctionnement


git merge combinera plusieurs séquences de commits en un historique unifié. Dans les cas d'usage les plus fréquents, git merge est utilisée pour combiner deux branches. Les exemples suivants dans ce document se concentreront sur ce modèle de merging de branches. Dans ces scénarios, git merge prend deux pointeurs de commit, généralement les pointes de la branche, et recherchera un commit de base commun aux deux. Dès que Git trouve un commit de base commun, il créera un nouveau « commit de merge » qui combine les changements de chaque séquence de commit de merge dans la file d'attente.

Supposons que nous ayons une nouvelle fonctionnalité de branche basée sur la branche (main). Nous souhaitons maintenant faire un merge de cette branche de fonctionnalité dans la branche (main).

Merger une branche fonctionnelle dans la branche main
Fenêtre de console
Ressource connexe

Commande git log avancée

Logo Bitbucket
DÉCOUVRIR LA SOLUTION

Découvrir Git avec Bitbucket Cloud

Appeler cette commande permettra de merger la fonctionnalité de branche spécifiée dans la branche actuelle, disons main. Git déterminera automatiquement l'algorithme de merge (abordé ci-dessous).

Nouveau nœud de commit de merge

Les commits de merge sont uniques par rapport aux autres commits, car ils ont deux commits parent. En créant un commit de merge, Git essaiera de merger automatiquement les historiques distincts à votre place. Si Git rencontre des données différentes dans les deux historiques, il ne pourra pas les combiner automatiquement. Ce scénario constitue un conflit de contrôle de version, et l'intervention d'un utilisateur sera nécessaire pour continuer.

Préparation du merge


Avant d'effectuer un merge, plusieurs étapes de préparation doivent être exécutées pour garantir un merge en douceur.

Confirmer la branche cible


Exécutez la commande git status pour vous assurer que HEAD pointe vers la branche recevant le merge correspondant. Si nécessaire, exécutez git checkout pour passer à la branche cible. Dans notre cas, nous exécuterons git checkout main.

Fetch des derniers commits distants


Assurez-vous que la branche cible et la branche mergée sont mises à jour avec les derniers changements distants. Exécutez la commande git fetch pour faire un pull des derniers commits distants. Une fois que le fetch est terminé, assurez-vous que la branche principale (main) est à jour en exécutant la commande git pull.

Merge


Après avoir exécuté les étapes de « préparation au merge » déjà évoqués, un merge peut être initié en exécutant git merge désigne le nom de la branche qui sera mergée dans la branche cible.

Fast-forward merge


Un fast-forward merge peut avoir lieu lorsque le chemin entre la pointe de la branche actuelle et la branche cible est linéaire. Plutôt que de réellement merger les branches, Git doit simplement déplacer (en « fast-forward ») la pointe de la branche actuelle vers celle de la branche cible pour intégrer les historiques. Cette opération est possible, puisque tous les commits accessibles à partir de la branche cible le deviennent également via la branche actuelle. Par exemple, un fast-forward merge de some-feature dans la branche (main) peut être schématisé comme suit :

Le nœud de fonctionnalité précède le nœud principal. Mais après le fast-forward, les deux se trouvent sur le même nœud.

Toutefois, un fast-forward merge n'est pas possible si les branches ont divergé. Lorsque le chemin vers la branche cible n'est pas linéaire, Git n'a d'autre choix que de combiner les branches avec un merge à trois branches. Les merges à trois branches utilisent un commit dédié pour lier deux historiques. La nomenclature vient du fait que Git utilise trois commits pour générer le commit de merge : les deux pointes de branche et leur ancêtre commun.

Diagramme après un merge à trois sources (3-way merge)

Bien que vous puissiez utiliser ces deux stratégies de merge, de nombreux développeurs aiment utiliser les fast-forward merges (simplifiés par le rebase) pour la correction de petites fonctionnalités ou de bugs mineurs, tout en réservant les merges à trois branches pour l'intégration de fonctionnalités utilisées à plus long terme. Le cas échéant, le commit de merge résultant permet d'établir un lien symbolique entre deux branches.

Notre premier exemple présente un fast-forward merge. Le code ci-dessous crée une nouvelle branche, y ajoute deux commits, puis l'intègre dans la ligne principale avec un fast-forward merge.

# Start a new feature
git checkout -b new-feature main
# Edit some files
git add <file>
git commit -m "Start a feature"
# Edit some files
git add <file>
git commit -m "Finish a feature"
# Merge in the new-feature branch
git checkout main
git merge new-feature
git branch -d new-feature

Il s'agit d'un workflow commun pour les branches topic éphémères qui sont davantage utilisées comme un développement isolé que comme un outil organisationnel pour les fonctionnalités utilisées à plus long terme.

Remarque : Git ne devrait pas réagir à la commande git branch -d, puisque la fonctionnalité new-feature est désormais accessible à partir de la branche principale.

Si vous avez besoin d'un commit de merge au cours d'un fast-forward merge à des fins d'archivage, vous pouvez exécuter la commande git merge avec l'option --no-ff.

git merge --no-ff <branch>

Cette commande fait un merge de la branche spécifiée dans la branche courante, mais génère toujours un commit de merge (même s'il s'agissait d'un fast-forward merge). Cela est utile pour documenter tous les merges qui se produisent dans votre dépôt.

Merge 'à trois sources' (3-way merge)


L'exemple suivant est très similaire, à cela près qu'un merge à trois branches est nécessaire, car la branche (main) avance tandis que la fonctionnalité est en cours de développement. Ce scénario n'est pas rare lorsque les fonctionnalités sont volumineuses ou que plusieurs développeurs travaillent simultanément sur un même projet.

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

Remarque : Git ne peut réaliser un fast-forward merge, puisqu'il est impossible de déplacer main vers new-feature sans backtracking.

Pour la plupart des workflows, new-feature serait une fonctionnalité bien plus volumineuse, dont le développement nécessiterait beaucoup de temps et qui justifierait l'apparition de nouveaux commits sur main entre-temps. Si votre branche de fonctionnalité est aussi petite que celle illustrée dans l'exemple ci-dessus, il est préférable d'en faire un rebase sur main et de réaliser un fast-forward merge. Ainsi, l'historique du projet ne sera pas pollué par des commits de merge superflus.

Résolution de conflits


Si les deux branches que vous essayez de merger modifient toutes les deux la même partie du même fichier, Git ne peut pas déterminer la version à utiliser. Lorsqu'une telle situation se produit, Git s'arrête avant le commit de merge, afin que vous puissiez résoudre manuellement les conflits.

L'avantage du merge dans Git est que le workflow habituel d'édition, d'indexation et de commit est utilisé pour résoudre les conflits de merge. Lorsque vous faites face à un conflit de merge, lancez la commande git status pour afficher les fichiers en conflit. Par exemple, si les deux branches modifient la même section de hello.py, le message suivant s'affiche à l'écran :

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

Présentation des conflits


Lorsque Git rencontre un conflit au cours d'un merge, il éditera le contenu des fichiers affectés avec des indicateurs visuels qui marquent les deux côtés du contenu en conflit. Ces marqueurs visuels sont les suivants : <<<<<<<, ======= et >>>>>>>. Il s'avère utile de rechercher ces indicateurs dans un projet au cours d'un merge pour savoir où des conflits doivent être résolus.

here is some content not affected by the conflict
<<<<<<< main
this is conflicted text from main
=======
this is conflicted text from feature branch
>>>>>>> feature branch;

En principe, le contenu situé avant le marqueur ======= représente la branche cible et la partie après ce marqueur représente la branche mergée.

Lorsque vous avez identifié les sections en conflit, vous pouvez faire le nécessaire pour résoudre le problème. Lorsque vous êtes prêt à terminer le merge, il vous suffit d'exécuter git add sur le(s) fichier(s) en conflit pour signaler à Git que le problème est résolu. Ensuite, lancez la commande git commit normalement pour générer le commit de merge. Le processus est exactement le même que pour commiter un instantané classique. Ainsi, les développeurs n'auront aucune difficulté à gérer leurs merges.

Notez que des conflits de merge se produiront également en cas de merge à trois branches. Il n'est pas possible d'avoir des changements en conflit dans un fast-forward merge.

Résumé


Ce document présente la commande git merge. Le merge est un processus essentiel lorsque vous travaillez avec Git. Nous avons déjà parlé des mécanismes internes à la base d'un merge et des différences entre un fast-forward merge et un véritable merge à trois branches. Voici quelques enseignements clés :

1. Le merging Git combine plusieurs séquences de commits en un historique de commits unifié.

2. Il existe deux types principaux de merges Git : fast-forward et à trois branches

3. Git peut merger automatiquement les commits, sauf si des changements entrent en conflit dans les deux séquences de commit.

Ce document intégrait et répertoriait d'autres commandes Git, notamment : git branch, git pull et git fetch. Consultez leurs pages respectives pour en savoir plus.


Partager cet article

Lectures recommandées

Ajoutez ces ressources à vos favoris pour en savoir plus sur les types d'équipes DevOps, ou pour les mises à jour continues de DevOps chez Atlassian.

Des personnes qui collaborent à l'aide d'un mur rempli d'outils

Le blog Bitbucket

Illustration DevOps

Parcours de formation DevOps

Démos Des démos avec des partenaires d'Atlassian

Fonctionnement de Bitbucket Cloud avec Atlassian Open DevOps

Inscrivez-vous à notre newsletter DevOps

Thank you for signing up