Mercurial: Branches nommées contre plusieurs repositorys

Nous utilisons actuellement subversion sur une base de code relativement grande. Chaque version a sa propre twig et les correctifs sont effectués sur le tronc et migrés dans des twigs de publication à l’aide de svnmerge.py

Je crois que le moment est venu de passer à un meilleur contrôle des sources, et je joue avec Mercurial depuis un moment.

Il semble y avoir deux écoles sur la gestion d’une telle structure de libération à l’aide de Mercurial. Soit chaque version a son propre référentiel, et des correctifs sont apportés à la twig de publication et poussés vers la twig principale (et toute autre twig de publication plus récente). OU utilisant des twigs nommées dans un même référentiel (ou plusieurs copies correspondantes).

Dans les deux cas, il semble que je puisse utiliser quelque chose comme la transplantation pour modifier les cerises pour les inclure dans les twigs de publication.

Je vous demande Quels sont les avantages relatifs de chaque approche?

La plus grande différence réside dans la manière dont les noms de twig sont enregistrés dans l’histoire. Avec les twigs nommées, le nom de la twig est incorporé dans chaque changeset et deviendra ainsi une partie immuable de l’histoire. Avec les clones, il n’y aura pas d’ enregistrement permanent de l’origine d’un changement particulier.

Cela signifie que les clones sont parfaits pour des expériences rapides où vous ne voulez pas enregistrer un nom de twig, et les twigs nommées sont bonnes pour les twigs à long terme (“1.x”, “2.x” et similaires).

Notez également qu’un seul référentiel peut facilement accueillir plusieurs twigs légères dans Mercurial. De telles twigs peuvent être mises en signet afin que vous puissiez facilement les retrouver. Supposons que vous ayez cloné le référentiel de la société à l’apparence suivante:

 [a] --- [b] 

Vous piratez et faites [x] et [y] :

 [a] --- [b] --- [x] --- [y] 

Pendant que quelqu’un met [c] et [d] dans le repository, quand vous tirez vous obtenez un graphique comme celui-ci:

             [x] --- [y]
            /
 [a B c d]

Ici, il y a deux têtes dans un même référentiel. Votre copie de travail reflétera toujours un seul ensemble de modifications, le soi-disant fichier de modifications parent de la copie de travail. Vérifiez ceci avec:

 % hg parents 

Disons que ça rapporte [y] . Vous pouvez voir les têtes avec

 % hg heads 

et cela rapportera [y] et [d] . Si vous souhaitez mettre à jour votre référentiel avec un checkout propre de [d] , faites simplement (remplacez [d] par le numéro de révision pour [d] ):

 % hg update --clean [d] 

Vous verrez alors que les hg parents rapportent [d] . Cela signifie que votre prochain commit aura [d] comme parent. Vous pouvez ainsi corriger un bug que vous avez remarqué dans la twig principale et créer des modifications [e] :

             [x] --- [y]
            /
 [a] --- [b] --- [c] --- [d] --- [e]

Pour pousser les modifications [e] seulement, vous devez faire

 % hg push -r [e] 

[e] est le hash de changeset. Par défaut, hg push va simplement comparer les référentiels et voir que [x] , [y] et [e] sont manquants, mais vous ne voudrez peut-être pas encore partager [x] et [y] .

Si le correctif vous affecte également, vous souhaitez le fusionner avec votre twig:

 % hg update [y] % hg merge 

Cela laissera votre graphique de référentiel comme ceci:

             [x] --- [y] ----------- [z]
            / /
 [a] --- [b] --- [c] --- [d] --- [e]

[z] est la fusion entre [y] et [e] . Vous pourriez aussi avoir choisi de jeter la twig:

 % hg ssortingp [x] 

Mon point principal de cette histoire est le suivant: un seul clone peut facilement représenter plusieurs pistes de développement. Cela a toujours été vrai pour “plain hg” sans utiliser aucune extension. L’ extension des favoris est une aide précieuse. Cela vous permettra d’atsortingbuer des noms (signets) aux changesets. Dans le cas ci-dessus, vous voudrez un signet sur votre tête de développement et un sur la tête en amont. Les signets peuvent être poussés et tirés avec Mercurial 1.6 et sont devenus une fonctionnalité intégrée dans Mercurial 1.8.

Si vous aviez choisi de créer deux clones, votre clone de développement aurait ressemblé à ceci après avoir créé [x] et [y] :

 [a] --- [b] --- [x] --- [y] 

Et votre clone en amont contiendra:

 [a] --- [b] --- [c] --- [d] 

Vous remarquez maintenant le bogue et le corrigez. Ici, vous n’avez pas à effectuer de hg update à hg update car le clone en amont est prêt à être utilisé. Vous vous engagez et créez [e] :

 [a] --- [b] --- [c] --- [d] --- [e] 

Pour inclure la correction de bogue dans votre clone de développement, vous pouvez y accéder:

 [a] --- [b] --- [x] --- [y]
            \
             [c] --- [d] --- [e]

et fusionner:

 [a] --- [b] --- [x] --- [y] --- [z]
            \ /
             [c] --- [d] --- [e]

Le graphique peut sembler différent, mais il a la même structure et le résultat final est le même. En utilisant les clones, vous deviez faire un peu moins de comptabilité mentale.

Les twigs nommées ne sont pas vraiment apparues ici car elles sont plutôt optionnelles. Mercurial lui-même a été développé en utilisant deux clones pendant des années avant d’utiliser des twigs nommées. Nous maintenons une twig appelée «stable» en plus de la twig «default» et faisons nos versions basées sur la twig «stable». Voir la page de twigment standard sur le wiki pour une description du stream de travail recommandé.

Je pense que vous voulez toute l’histoire en un seul repository. Un repo à court terme permet de réaliser des expériences à court terme, et non des événements majeurs tels que des versions.

L’une des déceptions de Mercurial est qu’il ne semble pas y avoir de moyen facile de créer une twig éphémère, de jouer avec elle, de l’abandonner et de ramasser les déchets. Les twigs sont pour toujours. Je sympathise avec le fait de ne jamais vouloir abandonner l’histoire, mais les twigs jetables super bon marché sont une caractéristique que je voudrais vraiment voir dans hg .

Vous devriez faire les deux .

Commencez par la réponse acceptée de @Norman: utilisez un référentiel avec une twig nommée par version.

Ensuite, ayez un clone par twig de publication pour la construction et le test.

Une note clé est que même si vous utilisez plusieurs référentiels, vous devriez éviter d’utiliser la transplant pour les déplacer car 1) il change de hachage et 2) il peut introduire des bogues très difficiles à détecter lorsqu’il y a des changements contradictoires entre l’ensemble de modifications. vous transplantez et la twig cible. Vous voulez faire la fusion habituelle à la place (et sans prémix: toujours inspecter visuellement la fusion), ce qui se traduira par ce que @mg a dit à la fin de sa réponse:

Le graphique peut sembler différent, mais il a la même structure et le résultat final est le même.

Plus verbalement, si vous utilisez plusieurs référentiels, le référentiel “trunk” (ou par défaut, main, development, etc.) contient TOUS les changements dans TOUS les référentiels. Chaque repository de release / branch est simplement une twig dans le tronc, tous fusionnés d’une manière ou d’une autre dans le tronc, jusqu’à ce que vous souhaitiez laisser une ancienne version. Par conséquent, la seule différence réelle entre ce référentiel principal et le référentiel unique dans le schéma de twig nommé est simplement de savoir si les twigs sont nommées ou non.

Cela devrait rendre évident pourquoi j’ai dit “commencer avec un repo”. Ce repo unique est le seul endroit où vous aurez besoin de rechercher des modifications dans une version . Vous pouvez en outre marquer les modifications sur les twigs de la version pour le contrôle de version. C’est conceptuellement clair et simple, et rend l’administration du système plus simple, car c’est la seule chose qui doit absolument être disponible et récupérable tout le temps.

Mais vous devez toujours conserver un clone par twig / version que vous devez créer et tester. C’est sortingvial car vous pouvez hg clone

#
, et puis hg pull dans le repo de twig ne fera que tirer de nouveaux ensembles de modifications sur cette twig (plus les modifications ancêtres sur les twigs précédentes fusionnées).

Cette configuration correspond le mieux au modèle de validation du kernel Linux de single puller (cela ne fait-il pas du bien d’agir comme Lord Linus? Dans notre société, nous appelons l’ intégrateur de rôle), extracteur doit tirer dans. La maintenance des mises en pension de succursales est uniquement destinée à la gestion des versions et peut être complètement automatisée. Les développeurs n’ont jamais besoin de passer / repousser dans les pensions de la twig.


Voici l’exemple de @ mg recasté pour cette configuration. Point de départ:

 [a] - [b] 

Créez une twig nommée pour une version finale, par exemple “1.0”, lorsque vous atteindrez la version alpha. Commencez par corriger les bogues:

 [a] - [b] ------------------ [m1] \ / (1.0) - [x] - [y] 

(1.0) n’est pas un vrai changeset puisque la twig nommée n’existe pas tant que vous ne vous êtes pas engagé. (Vous pouvez effectuer une validation sortingviale, telle que l’ajout d’une balise, pour vous assurer que les twigs nommées sont correctement créées.)

La fusion [m1] est la clé de cette configuration. Contrairement à un repository de développeur où il peut y avoir un nombre illimité de têtes, vous ne voulez pas avoir plusieurs têtes dans votre repository principal (sauf pour l’ancienne twig de version morte, comme mentionné précédemment). Donc, chaque fois que vous avez de nouveaux ensembles de modifications sur les twigs de la version, vous devez les fusionner immédiatement avec la twig par défaut (ou une twig de publication ultérieure). Cela garantit que toute correction de bogue dans une version est également incluse dans toutes les versions ultérieures.

En attendant, le développement sur la twig par défaut se poursuit vers la prochaine version:

  ------- [c] - [d] / [a] - [b] ------------------ [m1] \ / (1.0) - [x] - [y] 

Et comme d’habitude, vous devez fusionner les deux têtes par défaut:

  ------- [c] - [d] ------- / \ [a] - [b] ------------------ [m1] - [m2] \ / (1.0) - [x] - [y] 

Et voici le clone de la twig 1.0:

 [a] - [b] - (1.0) - [x] - [y] 

Maintenant, c’est un exercice pour append la prochaine twig de publication. Si c’est la version 2.0, alors il y aura certainement une dérivation par défaut. Si c’est 1.1, vous pouvez choisir de dérégler 1.0 ou par défaut. Quoi qu’il en soit, tout nouvel ensemble de modifications sur 1.0 doit d’abord être fusionné à la twig suivante, puis à la valeur par défaut. Cela peut être fait automatiquement s’il n’y a pas de conflit, résultant simplement en une fusion vide.


J’espère que cet exemple clarifie mes points précédents. En résumé, les avantages de cette approche sont les suivants:

  1. Un référentiel unique faisant autorité qui contient un historique complet des modifications et des versions.
  2. Gestion des versions claire et simplifiée.
  3. Flux de travail clair et simplifié pour les développeurs et intégrateurs.
  4. Faciliter les itérations de stream de travail (revues de code) et l’automatisation (fusion automatique à vide).

UPDATE hg lui – même le fait : le référentiel principal contient les twigs par défaut et stables, et le référentiel stable est le clone de twig stable. Cependant, il n’utilise pas de twigment versionné, car les balises de version le long de la twig stable sont suffisantes pour la gestion des versions.

La différence majeure, pour autant que je sache, est quelque chose que vous avez déjà déclaré: les twigs nommées sont regroupées dans un seul référentiel. Les twigs nommées ont tout à scope de main. Les repos séparés sont plus petits et faciles à déplacer. La raison pour laquelle il existe deux écoles de pensée à ce sujet est qu’il n’ya pas de gagnant évident. Les arguments les plus pertinents pour vous sont probablement ceux que vous devriez suivre, car leur environnement est probablement le même que le vôtre.

Je pense que c’est clairement une décision pragmatique en fonction de la situation actuelle, par exemple la taille d’une fonctionnalité / refonte. Je pense que les forks sont vraiment bien pour les consortingbuteurs avec des rôles qui ne sont pas encore au sharepoint rejoindre l’équipe de développeurs en prouvant leur aptitude à gérer des frais techniques négligeables.

Je déconseille vraiment d’utiliser des twigs nommées pour les versions. C’est vraiment ce que sont les tags. Les twigs nommées sont destinées à des détournements durables, comme une twig stable .

Alors pourquoi ne pas utiliser les tags? Un exemple de base:

  • Le développement se produit sur une seule twig
  • Chaque fois qu’une version est créée, vous la marquez en conséquence
  • Le développement continue juste à partir de là
  • Si vous avez des bogues à corriger (ou peu importe) dans une certaine version, il vous suffit de mettre à jour sa balise, d’apporter vos modifications et de vous engager.

Cela créera une nouvelle tête sans nom sur la twig default , alias. une twig anonyme, parfaitement bien en hg. Vous pouvez ensuite, à tout moment, fusionner la correction de bug renvoyée dans la piste de développement principale. Pas besoin de twigs nommées.