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 -d
supprimer 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
).
Ressource connexe
Commande git log avancée
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).
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
où
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 :
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.
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
Thème suivant
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.