Option A. Il suffit d'utiliser la ligne principale et de baliser pour la publication
Avantages:
-
Vous évitez de fusionner l'enfer.
-
Le maintien de la ligne principale encourage certaines des meilleures pratiques telles que la bonne planification des versions, n'introduisant pas beaucoup de WIP, utilisant la ramification par abstraction pour traiter le travail à long terme hors bande, et utilisant le système ouvert ouvert et les fonctionnalités configurables pour gérer la gestion des travaux en cours qui peut; ou pas; doivent être désactivés maintenant ou à l'avenir afin de libérer ou d'éviter une restauration complète.
Les inconvénients:
-
Le traitement des travaux en cours devient un problème et ajoute à la zone potentielle d'attaque de surface au moment de la libération. Cependant, si vos développeurs sont disciplinés, les nouvelles fonctionnalités doivent être configurables et modulaires et donc facilement désactivées / activées, ou il n'y a pas de WIP et à chaque point de sortie, tout le travail est terminé ou n'a pas encore été démarré (par exemple Scrum).
- Les changements à grande échelle / hors bande nécessitent plus de réflexion à l'avance pour être mis en œuvre (par exemple, ramification par abstraction).
Personnellement, je préfère cette approche. La couverture du code et les tests unitaires devraient identifier le code qui n'est pas prêt à sortir et les gens ne devraient pas travailler sur du code qui ne sera pas publié pendant l'itération en cours. La ramification par abstraction ou d'autres mécanismes peut être utilisée pour faire face aux changements à long terme et aux travaux en cours.
Lorsque vous ne le faites pas, vous commencez à vous retrouver avec des problèmes de fusion, du code périmé, des fonctionnalités qui ne sont jamais publiées, etc.
Option B. Branche par libération
Avantages:
- Vous pouvez commencer à travailler sur l'itération suivante pendant que l'itération actuelle termine son cycle de tests d'acceptation.
- D'autres trucs, je suis sûr.
Les inconvénients:
-
- Des tonnes de branches.
- Vous devez toujours baliser les branches aux points de sortie.
- Encore faut-il gérer le WIP et fusionner le WIP de la branche de la version précédente dans la branche de la prochaine version s'il ne réussit pas et doit toujours le désactiver ou le retirer de la branche de la version et réexécuter les tests d'acceptation
- Les correctifs doivent être appliqués à plus de branches (version branche + correctif + nouvelle balise + fusionner le correctif dans la branche vnext et éventuellement vnextnext selon l'endroit où le correctif se situe.)
Je ne suis pas un grand fan de cette solution ^ _ ^.
En général, je recommanderais simplement de rester fidèle à la ligne principale. Si vos développeurs ont du mal à ne pas écrire de WIP qui peut être facilement tiré en cas d'échec de la coupe ou qui est archivé tôt pour la prochaine version, vous pouvez commencer à parler du balisage du code au point où il devrait être terminé et se ramifier. à partir de là si nécessaire pour corriger les défauts et les bogues négligés que vos tests unitaires de développeurs n'ont pas réussi à détecter.
Idéalement, je pense que vous voulez que ce soit le processus d'exception, pas la règle.
Option C. Option Bonus fou
Si vous voulez devenir sophistiqué, vous pouvez également envisager un modèle de branchement par histoire d'utilisateur / par fonctionnalité. ( Une idée terrible dans TFS ou tout autre non DVCS tout en étant incroyablement triviale à mettre en œuvre si vous utilisez un DVCS comme git ou mercurial ).
Dans le passé, j'ai implémenté les éléments ci-dessous pour une équipe de maintenance d'employeurs précédente qui travaillait avec une base de code héritée qui ne pouvait pas être facilement transférée vers mercurial depuis svn. Beaucoup de travail inutile a été impliqué pour répondre à une exigence commerciale d'une ligne principale toujours libérable plutôt que de simplement mieux coordonner les versions, mais. . .
- Les fonctionnalités ont été développées par les développeurs dans la branche de développement de leurs équipes.
- Lorsqu'une fonctionnalité est prête à être examinée par les pairs, les développeurs la regroupent en une seule fusion de la branche Dev vers la branche CR et incluent l'ID de la fonctionnalité / histoire utilisateur dans le titre. * Appliqué par un crochet de pré-validation *
- Après avoir passé CR, un outil d'administration est utilisé pour promouvoir la fonctionnalité dans la branche QA. (J'ai écrit une petite application de terminal qui répertorie les user stories présentes dans les différentes étapes d'acceptation et permet à l'opérateur de la promouvoir ou de la rétrograder entre ces étapes d'acceptation)
- L'assurance qualité exécute des tests d'automatisation et d'utilisabilité manuelle. Si la fonctionnalité est bonne, elle est poussée dans la branche de publication (ligne principale). Si la fonctionnalité est rejetée, elle est rétrogradée / retirée de la branche QA jusqu'à ce que les développeurs puissent résoudre les problèmes soulevés pendant le test et ajouter soumettre un patch à la branche CR.
- Si le code a été rétabli à partir de la branche QA et qu'un correctif est appliqué, l'outil terminal réappliquera les modifications nécessaires pour ramener la fonctionnalité sur la branche QA à partir de la branche CR afin que QA puisse réexaminer le code et soit le promouvoir soit rétrograder à nouveau.
- À tout moment, la branche de publication doit être dans un état libérable stable.
- Après une version, les nouveaux Dev, QA et CR sont issus de la ligne principale.
Nous avons des branches distinctes pour chaque version que nous publions (environ 4 par an). Il est très pratique lorsque vous devez extraire une version spécifique.
Si vous avez besoin de conserver quelques versions plus anciennes, je ne pense pas que l'étiquetage ferait l'affaire. Avec des branches de versions spécifiques, vous pouvez appliquer des correctifs à chaque branche séparément (ou à une sélection d'entre elles) sans vous soucier des autres versions.
Cela facilite également la comparaison des versions lorsque vous recherchez le moment où un bogue ou une fonctionnalité a été introduit.
Ne vous inquiétez pas du nombre de succursales ou du temps qu'elles passent sans changements. Votre système de versioning vous donne le contrôle et fournit un historique du développement de votre projet. L'histoire a tendance à ne pas changer ... Et ne vous inquiétez pas si vos CV ne sont pas capables de faire face. Nous utilisons Perforce, plus de 9000 fichiers dans une branche de développement, jusqu'à 50 branches de développement pour les versions sur lesquelles nous travaillons et, comme déjà dit, une seule branche par version que nous publions. Perforce ne respire même pas plus fort.
En bref: simplifiez-vous la vie en tant que développeur / mainteneur / correcteur de bogues / chasseur de problèmes et ne vous inquiétez pas du nombre de branches ou du nombre de fichiers. Tout cv qui se respecte se débrouillera.
Éditer:
Nous ne souffrons pas du tout de confusion quant au nombre de succursales que nous avons. Notre schéma de dénomination pour les branches de publication et notre politique 1 branche 1 branche pour les branches de développement (ou de travail) peuvent avoir quelque chose à voir avec cela.
Les branches de version sont nommées en fonction de la version qu'elles détiennent, c'est-à-dire: R2011SP1 pour la version 2011 Service Pack 1. Nos branches de travail ont des noms moins intelligents: sub01, sub02, sub03 etc. Le "sub" vient du fait que toutes les branches de travail sont des sous-branches de la branche acceptation. La branche d'acceptation étant celle où sont collectés tous les problèmes prêts à être publiés.
Notre politique de branche de travail 1 problème 1, combinée au fait que notre système de suivi des problèmes a été personnalisé avec un champ "branche" garantit que nous savons toujours quel problème est développé dans quelle branche. Lorsqu'un problème est intégré dans la branche d'acceptation, ce champ est mis à jour. Cela signifie que nous savons toujours quels problèmes sont prêts à être publiés (une fois les tests d'acceptation terminés). De même, nous mettons à jour ce champ lorsqu'une branche de publication est créée et de cette façon, nous pouvons toujours retrouver la version publiée.
la source
Tout dépend du contexte: à quelle fréquence publiez-vous et ce qui se trouve dans une version.
Voici un peu une étude de cas que j'avais avec mon ancien travail, en utilisant la méthode B (nous l'avons appelé branche par objectif ).
Pour mettre l'histoire en contexte,
Le développement principal a été effectué dans le tronc jusqu'à ce que nous atteignions un état complet pour une certaine version. À ce stade, nous créerions une branche, par exemple projectname-janvier2012 et ferions nos tests de qualité et corrigions les bogues dans cette même branche. Une fois que nous étions prêts pour une version publique, nous étiquetions le code dans cette branche et le publions.
Cependant, le développement de la version ne s'est pas terminé à cette balise. Inévitablement, nous avons eu des clients qui ont trouvé des bogues ou de petits problèmes avec la version. Donc, dans ce cas, tout ce que nous devons faire est de revenir à cette branche, de corriger le code et de créer une nouvelle version balisée de la branche de janvier 2012 à publier, et de fusionner les correctifs dans le tronc.
Dans notre cas, cette approche était favorable car certains utilisateurs préféraient rester avec des versions plus anciennes avec un ensemble limité de fonctionnalités, ou tout simplement parce que le coût du déploiement sur leur infrastructure d'une toute nouvelle version plutôt que d'un correctif a causé certains problèmes.
Les questions que vous devez vous poser sont donc:
Si vous sortez souvent, cela ne vaut peut-être pas la peine d'avoir des branches pour chacun d'eux. Cependant, si votre cycle de publication est assez long comme mon ancien cas d'utilisation, et que le déploiement, la compatibilité descendante et les clients qui s'accrochent aux anciennes versions peuvent être des risques, l'option B vous épargnera certainement beaucoup de douleur, rendra les choses beaucoup plus faciles à prendre en charge vos clients au moindre coût lié à l'encombrement des succursales.
la source
Je préfère l'option A. Développer sur les versions de tronc et de branche lorsqu'elles sont stables. Cela limite considérablement le travail d'intégration des correctifs appliqués à la version de production.
J'ai été engagé pour aider une équipe qui a tenté l'option B à se remettre sur la bonne voie.
Quelques points à considérer.
la source
Je travaille depuis un certain nombre d'années sur un système qui utilise quelque chose entre les deux schémas que vous décrivez. L'essentiel est qu'il existe un schéma de numérotation à plusieurs niveaux. Le niveau externe est essentiellement la version de l'API, et il est géré sur des branches (avec des fusions croisées appropriées lorsque quelque chose doit être corrigé sur plusieurs branches) et le niveau interne correspond aux versions exactes effectuées, qui sont gérées avec des balises.
En particulier, si nous savons de quelle version exacte un client dispose, nous savons exactement à partir de quelle source le code a été créé et pouvons en faire un double exact afin que nous puissions voir exactement ce qui se passe. C'est très important pour le support! Pourtant, le niveau externe des branches, les versions d'API que nous publions actuellement, elles évoluent avec le temps (le principal tronc de développement obtenant la majorité des nouvelles fonctionnalités). De plus, lorsque nous faisons une nouvelle version majeure de l'API, nous faisons une nouvelle branche pour prendre en charge cela à partir de (afin que le tronc puisse toujours être orienté vers le développement dur) et nous nous demandons si nous devons mettre fin à la vie de la prise en charge la plus ancienne actuelle. branche.
Ainsi, je recommande quelque chose qui est vraiment un mélange de A et B ; les deux ont de bons aspects, mais aucun n'est complet en soi. Utilisez le meilleur des deux mondes.
la source
J'ai utilisé TFS pour implémenter efficacement l'option (B) dans le passé.
La ramification / fusion est un excellent outil lorsqu'elle est effectuée en petits morceaux. La difficulté ne réside pas dans la création d'une branche (c'est stupide facile), ni dans une semaine de travail pour sauvegarder l'arborescence (c'est généralement aussi facile) ... c'est dans le fait que le système CI derrière votre contrôle de source fonctionne automatiquement pour tu.
Parce que la branche est inutile si le système ne crée pas et n'exécute pas automatiquement des tests pour votre branche.
Nous avions personnalisé le workflow de construction par défaut de TFS pour reconnaître les chemins relatifs des changesets, et établi une convention par laquelle la personnalisation pouvait reconnaître une nouvelle branche (par opposition à simplement un nouveau sous-dossier sous une racine de développement). C'était lisse, facile à brancher, facile à tuer une branche, et nous avons reçu un retour continu de notre système pour les compilations et les tests.
Je vois beaucoup de gens déclarer à quel point ces stratégies sont impossibles sous TFS, et je pense que cela est dû à un manque de familiarité avec les possibilités d'un moteur de construction basé sur XAML. TFS n'est pas seulement le contrôle de code source, c'est une solution complète et doit être utilisé comme tel.
la source