Git utilise les branches pour isoler les flux de développement, afin d’éviter que la branche de la version stable ne soit polluée. Pour amener le travail d’une branche dans le flux principal, il faut fusionner les branches.
Qu’est-ce qu’une fusion dans Git ?
Git a été conçu pour rendre la création de branches simple et rapide. Contrairement à d’autres systèmes de contrôle de version, le branchement sur Git est une affaire triviale. Sur les projets multi-développeurs en particulier, le branchement est l’un des principaux outils d’organisation de Git.
Les branches servent de bac à sable pour les nouveaux efforts de développement afin que le code puisse être modifié ou ajouté sans affecter le code des autres branches, en particulier la branche principale ou master. Celle-ci contient généralement la version stable de votre base de code.
Isoler ces changements de la version stable de votre code est parfaitement logique. Mais tôt ou tard, le nouveau code sera testé, révisé et approuvé pour être intégré dans la branche principale. À ce moment-là, vous devez fusionner votre branche avec la branche principale.
En fait, les branches peuvent avoir des sous-branches, il se peut donc que vous fusionniez votre branche avec une autre branche au lieu de la branche principale. Rappelez-vous simplement que les fusions prennent toujours une branche et la fusionnent dans une branche cible, quelle que soit cette branche. Si vous souhaitez fusionner votre branche principale dans une autre branche, vous pouvez également le faire.
Comme la plupart des actions dans Git, vous effectuez les fusions dans votre référentiel local et les poussez vers votre référentiel distant.
Git rebase : Tout ce que vous devez savoir
Préparation de la fusion d’une branche dans Git
Nous avons un petit projet de développement avec un dépôt Git local et un dépôt Git distant. Nous avons créé une branche appelée « bugfix14 » à partir de la branche « master » et avons travaillé sur une solution à un bug.
Ce travail est terminé, et nous avons testé notre code. Tout fonctionne comme prévu. Nous voulons intégrer ces changements dans la branche « master » afin que notre solution fasse partie de la prochaine version du logiciel.
Il y a un peu de préparation à faire avant d’effectuer la fusion. Nous devons nous assurer que la branche cible – dans ce cas la branche « master » – et la branche que nous allons fusionner avec elle sont toutes deux à jour.
Pour ce faire, nous allons utiliser la commande git status.
git status
Utilisation de git status pour voir l’état d’une branche
Sur la branche bugfix14 : C’est notre branche actuelle.
Votre branche est à jour avec ‘origin/bugfix’ : La branche dans notre dépôt local a le même historique de commit que la branche dans le dépôt distant. Cela signifie qu’elles sont identiques.
Rien à commiter Il n’y a pas de changements dans la zone de transit qui n’ont pas été commis.
arbre de travail propre : Il n’y a pas de changements non validés dans le répertoire de travail.
Tous ces éléments indiquent que la branche est à jour, et que nous pouvons continuer. Si l’un de ces éléments indiquait l’existence de changements, nous devrions les mettre en scène, les livrer et les pousser sur le serveur distant. Si quelqu’un d’autre a travaillé sur ces fichiers, nous pouvons avoir besoin d’extraire leurs changements du dépôt distant.
Vérifier la branche dans laquelle nous allons fusionner simplifie le processus de fusion. Cela nous permet également de vérifier qu’elle est à jour. Jetons un coup d’oeil à la branche master.
git checkout master
git status
Extraction de la branche master et utilisation de git status pour voir son état.
Nous obtenons les mêmes confirmations que la branche » master » est à jour.
Réalisation d’une fusion
Avant la fusion, nos commits ressemblent à ceci.
L’historique des commits avant la fusion d’une branche
La branche « bugfix14 » a été dérivée de la branche « master ». Il y a eu un commit sur la branche « master » après la création de la branche « bugfix14 ». Il y a eu plusieurs commits sur la branche « bugfix14 ».
Nous nous sommes assurés que nos deux branches sont à jour, et nous avons vérifié la branche « master ». Nous pouvons lancer la commande pour fusionner la branche « bugfix14 » dans la branche « master ».
git merge bugfix14
Fusionner une branche avec la commande git merge
La fusion a lieu. La branche « bugfix14 » existe toujours, mais maintenant les changements qui ont été faits dans cette branche ont été fusionnés dans la branche « master ».
L’historique des livraisons après la fusion d’une branche
Dans cet exemple, la commande merge effectue une fusion à trois voies. Il n’y a que deux branches, mais il y a trois commits impliqués. Il s’agit de la tête de chaque branche, et d’un troisième commit qui représente l’action de fusion elle-même.
Pour mettre à jour notre dépôt distant, nous pouvons utiliser la commande git push.
git push
Pousser les changements vers un dépôt distant
Certaines personnes préfèrent supprimer les branches latérales une fois qu’elles les ont fusionnées. D’autres prennent soin de les préserver comme un enregistrement de la véritable histoire du développement du projet.
Si vous voulez supprimer la branche, vous pouvez le faire en utilisant la commande git branch avec l’option -d (delete).
git branch -d bugfix14
Suppression d’une branche dans le dépôt local
Pour supprimer la branche dans le dépôt distant, utilisez cette commande :
git push origin –delete bugfix14
Suppression d’une branche dans le dépôt distant
Vous aurez un historique de commit linéaire, mais ce ne sera pas le véritable historique.
Effectuer une fusion rapide dans Git
Si vous n’avez pas fait de commits sur la branche » master « , votre historique ressemblera à ceci. Il ressemblera également à ceci si vous avez modifié votre branche de développement pour qu’elle soit attachée à la fin de la branche « master ».
L’historique des modifications avant une fusion rapide
Comme il n’y a pas de commits dans la branche « master », pour fusionner la branche « bugfix15 », tout ce que Git doit faire est de pointer le pointeur de tête de « master » vers le dernier commit de la branche « bugfix15 ».
Nous pouvons utiliser la commande git merge habituelle :
git merge bugfix15
Cela nous donne ce résultat.
Une façon de visualiser le résultat d’une fusion rapide
Ce qui est identique à ceci :
Une autre façon de voir le résultat d’une fusion rapide
Ce qui est la même chose que ceci :
Encore une autre façon de voir le résultat d’une fusion rapide
Git effectue une fusion rapide dès qu’il le peut. Si les commits vers la branche « master » signifient qu’une fusion rapide n’est pas possible, Git utilisera une fusion à trois voies.
Vous ne pouvez pas forcer une fusion rapide – il se peut qu’elle ne soit pas possible, après tout – mais vous pouvez déclarer que c’est la fusion rapide ou rien. Il existe une option qui indique à Git d’utiliser une fusion rapide si elle le peut, mais de ne pas faire de fusion à trois s’il ne le peut pas. L’option est –ff-only (fast-forward merge only).
Ceci fusionne la branche « bugfix15 » dans la branche « master », mais seulement si une fusion rapide est possible.
git merge –ff-only bugfix15
Utilisation de l’option –ff-only pour empêcher l’utilisation d’une fusion à trois si une fusion rapide n’est pas possible.
Git se plaindra et quittera si cela n’est pas possible.
git merge –ff-only bugfix16
Git n’effectue aucune fusion car une fusion rapide n’est pas possible et l’option –ff-only a été utilisée.
Dans ce cas, il y a eu des commits sur la branche « master », donc une fusion rapide n’est pas possible.
Comment résoudre les conflits de fusion dans Git ?
Si les mêmes portions du même fichier ont été modifiées dans les deux branches, les branches ne peuvent pas être fusionnées. Une interaction humaine est nécessaire pour résoudre les éditions conflictuelles.
Ici, nous avons apporté des modifications à un fichier appelé « rot.c » dans une branche appelée « bugfix17 » que nous voulons fusionner avec la branche « master ». Mais « rot.c » a aussi été modifié dans la branche « master ».
git merge bugfix17
Obtenir le signalement de conflits et l’arrêt d’une fusion
Lorsque nous essayons de fusionner, nous recevons un avertissement indiquant qu’il y a des conflits. Git liste les fichiers en conflit, et nous indique que la fusion a échoué. Nous pouvons faire marche arrière en utilisant l’option –abort :
git merge –abort
Mais la résolution des fusions n’est pas aussi effrayante qu’il n’y paraît. Git a fait un certain travail pour nous aider. Si nous éditons l’un des fichiers en conflit – dans notre cas, nous n’en avons qu’un – nous trouverons les sections de code en conflit mises en évidence pour nous.
Comment git identifie les conflits dans un fichier
Chaque conflit est délimité par sept caractères inférieurs à « <<<<<<< » et sept caractères supérieurs à « >>>>>>> », avec sept signes égaux à « ======= » entre eux.
Le code au-dessus des signes égaux est celui de la branche dans laquelle vous fusionnez.
Le code sous le signe égal est le code de la branche que vous essayez de fusionner.
Vous pouvez facilement rechercher l’un des ensembles de sept caractères et vous déplacer de conflit en conflit dans votre fichier. Pour chaque conflit, vous devez choisir l’ensemble des modifications que vous allez conserver. Vous devez éditer le code que vous rejetez, et les lignes de sept caractères que Git a ajoutées.
Nous allons conserver le code de la branche « bugfix17 ». Après édition, notre fichier ressemble à ceci.
Le texte édité, résolvant le conflit de fusion
Nous pouvons maintenant poursuivre la fusion. Mais attention, nous utilisons la commande commit pour le faire, pas la commande merge.
Nous validons la modification en mettant le fichier à disposition et en le validant comme d’habitude. Nous allons vérifier le statut avant de faire le commit final.
git add rot.c
git status
git commit -m « Fusionné bugfix17 » (en anglais)
Utilisation de la commande commit pour terminer une fusion après avoir résolu les conflits
La fusion est terminée. Nous pouvons maintenant la pousser vers notre dépôt distant.
Tout finit par fusionner
Toutes les branches doivent être fusionnées, à terme, afin que les changements qu’elles contiennent ne deviennent pas orphelins et oubliés.
La fusion des branches est facile, mais la gestion des conflits peut s’avérer compliquée dans des équipes plus importantes et très occupées. La résolution des conflits peut nécessiter l’intervention de chaque développeur pour expliquer ce que fait son code et pourquoi il a apporté des modifications. Vous devez comprendre cela, avant de pouvoir prendre une décision éclairée sur les modifications à conserver.
Malheureusement, Git ne peut pas vous aider dans ce domaine.