Mercurial pour nous les nuls, leçon 9 : merge

L’index des leçons :

  1. Leçon 1 : la gestion de version
  2. Leçon 2 : qu’est-ce qu’un dépôt ?
  3. Leçon 3 : les logiciels ”clients”
  4. Leçon 4 : création d’un dépôt
  5. Leçon 5 : enregistrement de révision
  6. Leçon 6 : synchronisation de dépôts, mise à jour du répertoire de travail
  7. Leçon 7 : identifier les différences
  8. Leçon 8 : la gestion des branches
  9. Leçon 9 : la fusion de branche
  10. Leçon 10 : retour vers le passé
  11. Leçon 11 : patch et collaboration indirecte

Nous voilà maintenant avec deux branches en cours de développement. Pour faire suite à tous les commits effectués dans la leçon précédente il va falloir synchroniser le dépôt distant. Le logiciel MacHg n’est pour l’instant pas capable de faire un push directement lorsqu’une nouvelle branche fait partie du lot des révisions à envoyer. Il est donc nécessaire d’utiliser une commande terminal.

MacHg propose nativement de lancer une session terminal correctement configurée pour pouvoir effectuer des opérations sur nos dépôts. Pour faire pon push je vais alors exécuter la commande suivante :

mhg push --new-branch <url-depot-distant>

Vous avez noté ici la légère différence sur le début de la commande, mhg au lieu du hg que vous rencontré dans les leçons précédentes. C’est tout simplement parce MacHg, qui intègre une version de Mercurial, pour ne pas entrer en éventuel conflit avec une version déjà installée sur votre ordinateur, utilise une version renommée en mhg. Toute la syntaxe des commandes restant bien évidemment identique.

Me voilà maintenant avec un dépôt distant et un dépôt local synchronisé comme en témoigne les compteurs :

Dépôts local et distant synchronisés

Passés quelques jours, les deux branches ont évolué chacune de leur côté et il est temps d’envisager de fusionner les travaux.

Fusion de branche

Voilà maintenant l’état de mon dépôt :

État du dépôt après l'avancement sur les deux branches

Vous observerez que la branche default a reçu 3 commits (révisions 5, 7 et 8) et que la branche config en a reçu 3 également (révisions 4, 6 et 9).

Pour l’instant mon répertoire de travail reflète la branche default et je souhaite fusionner ce qui a été fait sur la branche config pour bénéficier du travail qui y a été effectué. Pour cela je vais utiliser la commande merge disponible sur la barre d’outils :

Bouton Merge sur la barre d'outils

MacHg m’indique la révision active 8 (en violet pâle) et je sélectionne la révision 9 que je veux fusionner avec la révision courante. Il m’indique alors ce qui adviendra : “The revision selected above (9) will be merged into the current revision (8).” soit en anglais ce que j’ai dit dans la phase précédente — ce qui tombe assez bien finalement !

Choix de la branche à fusionner

MacHg me permet, avant de lancer le merge (la fusion en anglais), de vérifier les différences entre les deux révisions. Voilà un exemple de ce qu’on peut obtenir en utilisant le bouton View Differences :

Différences entre deux révisions

Vous voyez que le fichier _public.php a été modifié dans les deux branches, la colonne de gauche représentant l’état de la révision 9 (branche config) et la colonne de droite représentant l’état de la révision 8 (branche default). Les parties rouges indiquent des suppressions, les vertes des ajouts et les violettes des modifications.

Lorsque je valide en cliquant sur le bouton Merge, MacHg compare les fichiers et dossiers. Si un fichier n’a pas été modifié ou n’existe pas dans le répertoire de travail alors qu’il l’est dans la branche à fusionner alors il l’ajoute directement. Par contre, si un fichier a été modifié dans les deux branches, MacHg me propose alors de résoudre ce conflit.

La commande terminal équivalente est la suivante (9 est le numéro de la révision à fusionner avec la branche courante) :

hg merge -r 9

Résolution de conflit

Dans le merge qui nous occupe, deux fichiers ont été modifiés dans les deux branches : _define.php où un numéro de version à été changé et _public.php dont les modifications sont visibles sur la différence des révisions illustrée plus haut.

Pour résoudre ces conflits il faut alors utiliser un outil qui va nous permettre de spécifier, pour chacune des modifications existantes — qu’elles soient présentes dans l’une ou l’autre des branches à fusionner — ce qu’on décide de garder, modifier ou ignorer. Sur Mac OS X j’ai sélectionné une application nommée DiffMerge qui permet justement de ces opérations — cette application fonctionne également sur Windows et Linux et est à mon avis la plus facile à appréhender.[1].

Pour le premier fichier, _define.php, voilà ce que DiffMerge, appelé par MacHg pour résoudre ce premier conflit, me propose :

L'outil de résolution de conflit DiffMerge

Je ne vais pas entrer dans le détail de l’utilisation de cet outil mais simplement signaler très succinctement que :

  • L’affichage présente trois colonnes :
    • une première à gauche avec le fichier dans son état actuel dans le répertoire de travail ;
    • une deuxième au centre qui présente l’état final qu’aura le fichier[2] ;
    • une troisième colonne à droite qui présente le fichier en provenance de la branche à fusionner.
  • Une barre d’outils vous permet :
    • de parcourir les différentes modifications ;
    • de choisir si la modification à conserver doit être prise dans la colonne de gauche ou de droite ;
    • de sauvegarder le fichier final (représenté par la colonne centrale).

Pour ce fichier je choisis de conserver la plus haute valeur du numéro de version spécifié dans le code (colonne de gauche et donc branche default), je sauvegarde le résultat et ferme la fenêtre (ce qu’attendait MacHg pour me proposer la suite de la fusion).

Pour le second fichier, _public.php, j’ai récupéré à droite et à gauche ce qui me paraissait le plus opportun et j’en ai profité pour modifier au passage le code résultant. Voilà le résultat, juste avant la sauvegarde :

Fusion des modifications du code présent dans le fichier avec DiffMerge

Une fois cette résolution des conflits terminée, MacHg m’informe qu’il va falloir faire un commit pour enregistrer le résultat du merge :

Message de fin de fusion

Puis m’indique la fin de la fusion avec un message récapitulatif :

Résultat du merge

Observons maintenant la liste des révisions :

Liste des révisions après le merge

Vous voyez que les deux branches se rejoignent (lignes en pointillé) et que le prochain commit permettra d’enregistrer cela dans le dépôt. Ce que je fais immédiatement avant de faire un push pour synchroniser mon dépôt distant. Je me retrouve alors avec une branche default dans laquelle j’ai rapatrié les modifications effectuées dans la branche config :

État des révisions après le commit qui suit le merge

Notez que je peux tout à fait continuer le travail sur la branche config, il suffit pour cela d’utiliser la commande update, sans répercutions sur la branche default.

Si je souhaite fermer définitivement la branche config il faut alors, après avoir fait un update vers la dernière révision de la branche config, sous terminal (MacHg n’est pas encore capable de le faire nativement), faire :

hg commit --close-branch -m 'fermeture branche config'

Conclusion

Vous savez maintenant l’indispensable pour gérer des dépôts Mercurial sur lesquels peuvent coexister plusieurs branches de développement que l’on peut fusionner en fonction des besoins. Vous pouvez ainsi créer autant de branches que vous le souhaitez, les fusionner, voire même les fermer si elles ne vous servent plus.

Nous verrons dans la prochaine leçon comment faire pour annuler le dernier commit, voire de supprimer toute une série de révision sur un dépôt. Ça peut parfois servir, d’ailleurs ça l’a été pour le projet Dotclear où il a fallu faire un strip (suppression sans retour en arrière possible d’une série de révisions) assez conséquent.

Glossaire

merge : fusion de deux branches.

Pour en savoir plus

  • Wikipedia : La fusion (logiciels de gestion de version)

Leçon suivante

Notes

[1] D’autres applications permettant ces opérations sont disponibles sur Mac OS X, Windows ou Linux, et fonctionnent sur le même principe.

[2] Notez que l’édition est possible dans cette colonne et que vous pouvez donc y apporter toutes les modifications que vous souhaitez.

Ajouter un commentaire

Les champs suivis d'un * sont obligatoires

Les commentaires peuvent être formatés en utilisant la syntaxe Markdown Extra.

Ajouter un rétrolien

URL de rétrolien : https://open-time.net/trackback/7132

Haut de page