Que sont les conflits de fusion ?

Effectué

Nous expliquons ici comment la résolution des conflits de fusion aide les développeurs à produire le résultat optimal à partir de deux sources qui se chevauchent.

Flux GitHub

En plus de fournir une plateforme pour le développement de logiciels collaboratifs, GitHub offre également un workflow prescrit conçu pour optimiser l’utilisation de ses différentes fonctionnalités. Comme cette unité couvre spécifiquement les conflits de fusion, nous vous recommandons de commencer par Présentation du flux GitHub.

Fusion de branches

Imaginez un scénario dans lequel un développeur crée une branche nommée feature-branch basée sur main et crée deux commits. Pendant que ce travail se déroule, une autre personne fusionne une demande de tirage non liée dans main. Que se passe-t-il quand notre développeur tente de refusionner feature-branch dans main ?

Réponse : cela dépend.

Même si feature-branch a été créée à partir de main, elle n’était pas basée sur la branche elle-même. Elle était plutôt basée sur le commit HEAD de main à ce moment-là. Elle n’a pas connaissance de tous les commits qui ont été appliqués à main depuis lors. Les commits qu’elle suit actuellement ne vont pas nécessairement être répliqués dans l’état actuel de la branche sans remplacer des modifications récentes.

S’il s’avère que les commits de feature-branch et les commits parallèles effectués sur main depuis la création de la branche ne se chevauchent pas, il n’y a pas de problèmes. De nouveaux fichiers peuvent être ajoutés. Les fichiers non modifiés peuvent être supprimés. Les lignes de code qui ont été modifiées dans main peuvent être modifiées dans feature-branch tant que le travail parallèle ne les a pas changées depuis la création de feature-branch.

A pull request with no merge conflicts.

Mais que se passe-t-il si les deux ensembles de commits incluent des modifications dans les mêmes lignes de code ? Cette tentative de fusion échoue en raison d’un conflit de fusion.

A merge conflict.

Que sont les conflits de fusion ?

Les conflits de fusion sont déclenchés lorsqu’un développeur tente de fusionner des modifications qui remplaceraient par inadvertance des modifications parallèles. Peu importe la façon dont ces autres modifications ont été fusionnées dans la branche de base. Git ne remplace pas automatiquement un ensemble de modifications en faveur d’un autre. Au lieu de cela, il les signale à la personne qui tente de les fusionner pour qu’elle puisse les résoudre sur sa branche de comparaison avant de tenter une nouvelle fusion.

A pull request with merge conflicts.

Résolution des conflits de fusion

Pour vous aider à résoudre les conflits de fusion, GitHub génère un fichier hybride temporaire qui contient les différences de chaque branche. L’usage veut que le texte de la branche de comparaison soit affiché au-dessus de la branche de base, séparé par une ligne de signes égal (=======).

Resolving a merge conflict.

Vous pouvez utiliser cette vue pour modifier directement le fichier si les modifications sont mineures. Si vous décidez de conserver le résultat final, il est commité dans la branche de comparaison. Sinon, si la fusion est plus complexe, vous pouvez préférer travailler sur celle-ci avec d’autres outils de développement. Dans les deux cas, n’oubliez pas de supprimer les marqueurs de branche de votre code avant de commiter. Si vous oubliez de supprimer ces marqueurs quand vous commitez la résolution des conflits, ils restent dans le fichier et ne sont pas mis en commentaire.

Remarque

Cette unité traite de la résolution des conflits de fusion dans le contexte d’un navigateur. Il existe également de nombreuses plateformes de développement, telles que Visual Studio, qui offrent des expériences de résolution de conflit de fusion intégrées.

Une fois que tous les conflits de fusion ont été résolus sur votre branche, vous pouvez retenter la fusion.

Prévention des conflits de fusion

Certains conflits de fusion sont inévitables. Toute fusion peut potentiellement générer des conflits de fusion pour d’autres demandes de tirage en attente d’approbation. Toutefois, une façon efficace de réduire la complexité des conflits de fusion consiste à extraire souvent votre branche.

Extraire de manière anticipée et fréquente

La commande git pull extrait tous les commits de la branche de base qui n’ont pas encore été appliqués à votre branche actuelle. Elle est similaire d’un point de vue conceptuel à la commande Get Latest (Obtenir la dernière version) que de nombreux systèmes de gestion de versions utilisent pour vous permettre de mettre à jour votre code local vers la dernière version. Quand vous extrayez des mises à jour pour votre branche, vous fusionnez toutes les modifications qui se sont produites depuis la création (ou la dernière extraction) de la branche.

L’extraction des mises à jour sur votre branche peut entraîner des conflits de fusion, mais c’est normal. Ces conflits se seraient de toute façon produits plus tard, et plus ils sont traités tôt, plus ils sont en général faciles à résoudre.

En plus de limiter l’impact des conflits de fusion, l’extraction des mises à jour vous permet également d’intégrer les modifications commitées dans votre branche à mesure que vous travaillez. Cela vous permet d’identifier les problèmes potentiels plus tôt. Par exemple, des modifications de définition de classe dans d’autres fichiers peuvent faire que votre code ne se compile plus. Ce modification n’aurait pas provoqué un conflit de fusion lors d’une fusion ultérieure, mais la build aurait été interrompue si vous ne l’aviez pas d’abord testée. Il est recommandé d’extraire souvent les mises à jour pour que votre branche soit aussi proche que possible de sa base.

Historique de nettoyage avec git rebase

La commande git rebase (ou git pull --rebase) réécrit l’historique de votre branche pour utiliser le commit HEAD actuel de la branche de base comme base. En d’autres termes, votre branche est mise à jour pour qu’elle se comporte comme si elle était créée à partir de l’état actuel de la branche de base. Ce rebasement signifie que toutes vos modifications sont comparées à l’état le plus récent de la branche de base, et non pas au commit d’origine à partir duquel vous avez créé la branche. Le rebasement peut rendre l’historique plus facile à suivre après votre fusion finale, car vos commits vont suivre les commits parallèles précédents de façon linéaire. Il est recommandé de rebaser votre branche immédiatement avant la fusion en amont.

Découvrez-en plus sur git rebase et la résolution des conflits de fusion après une opération git rebase.