web-dev-qa-db-fra.com

Meilleure stratégie de branchement lors d'une intégration continue?

Quelle est la meilleure stratégie de branchement à utiliser lorsque vous souhaitez effectuer une intégration continue?

  1. Release Branching: développer sur le tronc, garder une branche pour chaque version.
  2. Feature Branching: développer chaque fonctionnalité dans une branche distincte, fusionner uniquement une fois stable.

Est-il judicieux d'utiliser ces deux stratégies ensemble? Comme dans, vous branchez pour chaque version mais vous branchez aussi pour les grandes fonctionnalités? L'une de ces stratégies correspond-elle mieux à une intégration continue? L'utilisation d'une intégration continue aurait-elle même du sens lors de l'utilisation d'un tronc instable?

99
KingNestor

Je trouve le sujet vraiment intéressant car je compte beaucoup sur les branches dans mon travail quotidien.

  • Je me souviens que Mark Shuttleworth avait proposé un modèle pour garder la branche principale vierge tout en allant au-delà des CI conventionnels. J'ai posté à ce sujet ici .
  • Depuis que je connais Cruise Control, j'ai également blogué sur les branches de tâches et CI ici . C'est un tutoriel étape par étape expliquant comment le faire avec Plastic SCM .
  • Enfin, j'ai trouvé certains des sujets sur CI (et potentiellement parler de ramification) dans le livre de Duvall sur CI très intéressant aussi .

J'espère que vous trouverez les liens intéressants.

20
pablo

La réponse dépend de la taille de votre équipe et de la qualité de votre contrôle de source et de la possibilité de fusionner correctement des ensembles de modifications complexes. Par exemple, dans le contrôle de source de branche complète comme la fusion CVS ou SVN, il peut être difficile et vous pourriez être mieux avec le premier modèle, tandis que si vous utilisez un système plus complexe comme IBM ClearCase et avec une équipe plus grande, vous pourriez être meilleur avec le second modèle ou une combinaison des deux.

Personnellement, je séparerais le modèle de branche de fonctionnalité, où chaque fonctionnalité principale est développée sur une branche distincte, avec des sous-branches de tâche pour chaque changement effectué par un développeur individuel. Au fur et à mesure que les fonctionnalités se stabilisent, elles sont fusionnées dans le tronc, ce qui vous permet de rester raisonnablement stable et de réussir tous les tests de régression à tout moment. Lorsque vous approchez de la fin de votre cycle de publication et que toutes les branches de fonctionnalités fusionnent, vous stabilisez et branchez une branche du système de publication sur laquelle vous ne faites que des corrections de bogues de stabilité et des rétroportages nécessaires, tandis que le tronc est utilisé pour le développement de la prochaine version et vous recommencez. dériver pour de nouvelles branches de fonctionnalité. Etc.

De cette façon, le tronc contient toujours le code le plus récent, mais vous parvenez à le garder raisonnablement stable, en créant des étiquettes (balises) stables lors des changements majeurs et des fusions de fonctionnalités, les branches des fonctionnalités sont un développement rapide avec une intégration continue et les sous-branches de tâches individuelles peuvent être souvent actualisé à partir de la branche de fonctionnalité pour que tout le monde travaille sur la même fonctionnalité en synchronisation, sans affecter simultanément les autres équipes travaillant sur des fonctionnalités différentes.

Dans le même temps, vous avez à travers l'historique un ensemble de branches de publication, où vous pouvez fournir des rétroportages, du support et des corrections de bugs pour vos clients qui, pour une raison quelconque, restent sur les versions précédentes de votre produit ou même sur la dernière version publiée. Comme avec le tronc, vous ne configurez pas l'intégration continue sur les branches de versions, elles sont soigneusement intégrées lors de la réussite de tous les tests de régression et autres contrôles de qualité des versions.

Si, pour une raison quelconque, deux fonctionnalités sont co-dépendantes et nécessitent des modifications l'une de l'autre, vous pouvez envisager de développer les deux sur la même branche de fonctionnalité ou d'exiger que les fonctionnalités fusionnent régulièrement des parties stables du code vers le tronc, puis actualisez les modifications à partir de trunk pour échanger du code entre les branches de trunk. Ou si vous devez isoler ces deux fonctionnalités des autres, vous pouvez créer une branche commune à partir de laquelle vous branchez ces branches de fonctionnalité et que vous pouvez utiliser pour échanger du code entre les fonctionnalités.

Le modèle ci-dessus n'a pas beaucoup de sens avec des équipes de moins de 50 développeurs et un système de contrôle de source sans succursales clairsemées et une capacité de fusion appropriée comme CVS ou SVN, ce qui ferait de tout ce modèle un cauchemar à configurer, gérer et intégrer.

20
Jiri Klouda

Personnellement, je trouve beaucoup plus propre d'avoir un tronc stable et de créer des branchements. De cette façon, les testeurs et similaires peuvent rester sur une seule "version" et mettre à jour à partir du tronc pour tester toute fonctionnalité dont le code est complet.

De plus, si plusieurs développeurs travaillent sur différentes fonctionnalités, ils peuvent tous avoir leurs propres branches distinctes, puis fusionner dans le tronc une fois terminé et envoyer une fonctionnalité à tester sans que le testeur n'ait à basculer sur plusieurs branches pour tester différentes fonctionnalités.

En prime, il existe un certain niveau de test d'intégration qui vient automatiquement.

9
Adnan

Les branches de publication sont très utiles, voire absolument nécessaires, si vous avez besoin de maintenir plusieurs versions de votre application.

Les branches de fonctionnalités sont également très pratiques, notamment si un développeur doit travailler sur un changement énorme, tandis que d'autres publient toujours de nouvelles versions.

Donc, pour moi, utiliser les deux mécanismes est une très bonne stratégie.

Lien intéressant du Livre de SVN .

5
SirFabel

Je pense que l'une ou l'autre stratégie peut être utilisée avec un développement continu à condition que vous vous souveniez de l'un des principes clés que chaque développeur s'engage quotidiennement sur le trunk/mainline.

http://martinfowler.com/articles/continuousIntegration.html#EveryoneCommitsToTheMainlineEveryDay

MODIFIER

J'ai fait une lecture de ce livre sur CI et les auteurs suggèrent que le branchement par version est leur stratégie de branchement préférée. Je suis d'accord. La ramification par fonctionnalité n'a aucun sens pour moi lors de l'utilisation de CI.

Je vais essayer d'expliquer pourquoi je pense de cette façon. Supposons que trois développeurs prennent chacun une branche pour travailler sur une fonctionnalité. Chaque fonctionnalité prendra plusieurs jours ou semaines pour se terminer. Pour s'assurer que l'équipe s'intègre continuellement, elle doit s'engager dans la branche principale au moins une fois par jour. Dès qu'ils commencent à le faire, ils perdent l'avantage de créer une branche de fonctionnalité. Leurs changements ne sont plus séparés de tous les autres changements du développeur. Cela étant, pourquoi s'embêter à créer des branches de fonctionnalités en premier lieu?

L'utilisation de la branche par version nécessite beaucoup moins de fusion entre les branches (toujours une bonne chose), garantit que toutes les modifications sont intégrées dès que possible et (si elles sont effectuées correctement) garantit que votre base de code est toujours prête à être publiée. L'inconvénient de la ramification par version est que vous devez être beaucoup plus prudent avec les modifications. Par exemple. Une refactorisation importante doit être effectuée de manière incrémentielle et si vous avez déjà intégré une nouvelle fonctionnalité dont vous ne voulez pas dans la prochaine version, elle doit être masquée à l'aide d'une sorte de mécanisme basculement de fonctionnalité .

UNE AUTRE MODIFICATION

Il existe plusieurs opinions à ce sujet. Voici un article de blog qui se ramifie avec CI

http://jamesmckay.net/2011/07/why-does-martin-fowler-not-understand-feature-branches/

5
Phil Hale

J'ai récemment appris à aimer ce modèle lors de l'utilisation de git. Bien que votre question soit étiquetée "svn", vous pourrez peut-être encore l'utiliser.

L'intégration continue peut dans une certaine mesure se produire dans la branche "développer" (ou comme vous l'appelez) dans ce modèle, bien que le fait d'avoir des branches de fonctionnalités de longue durée pour les versions futures ne rendrait pas assez rigide pour considérer chaque changement se produisant quelque part. La question demeure, si vous voulez vraiment cela. Martin Fowler le fait.

4
hermannloose

Tant que vous comprenez les principes, vous pouvez toujours réinventer les meilleures pratiques. Si vous ne comprenez pas les principes, les meilleures pratiques vous amèneront aussi loin avant de s'effondrer en raison de certaines exigences externes contradictoires.

Pour une meilleure introduction au modèle Mainline, lisez ceci: https://web.archive.org/web/20120304070315/http://oreilly.com/catalog/practicalperforce/chapter/ch07.pdf

Lisez le lien. Une fois les bases acquises, lisez l'article suivant du vénérable Henrik Kniberg. Il vous aidera à associer le modèle Mainline à une intégration continue.

http://www.infoq.com/articles/agile-version-control

2
zvolkov

L'intégration continue ne doit pas être un facteur dans la détermination de votre stratégie de branchement. Votre approche de branchement doit être sélectionnée en fonction de votre équipe, du système en cours de développement et des outils à votre disposition.

Ayant dit cela ...

  • il n'y a aucune raison pour que CI ne puisse pas être utilisé dans les deux approches que vous décrivez
  • ces approches fonctionnent très bien en combinaison
  • aucun des deux ne fonctionne "mieux" que l'autre
  • CI a un sens total avec un tronc instable

Tout cela a été répondu dans la quatrième question sur la page à partir de laquelle vous avez pris les diagrammes: http://blogs.collab.net/Subversion/2007/11/branching-strat/

2
Zac Thompson

Lorsque nous avons commencé notre équipe, nous avons hérité d'une stratégie basée sur les versions du fournisseur qui a initialement développé le système que nous étions sur le point de prendre en charge. Cela a fonctionné jusqu'au moment où nos clients ont demandé que plusieurs fonctionnalités développées ne soient pas incluses dans une version (f.y.i. ~ 250k lignes de code, ~ 2500 fichiers, Scrum avec XP SDLC).

Ensuite, nous avons commencé à examiner les branches basées sur les fonctionnalités. Cela a également fonctionné pendant un certain temps - comme 2 mois jusqu'à ce que nous réalisions que notre processus de test de régression prendrait plus de 2 semaines, ce qui, combiné à l'incertitude de ce qui serait publié, créait un énorme inconvénient.

Le dernier "clou dans le cercueil" des stratégies pures SC est venu lorsque nous avons décidé que nous devrions avoir 1. un tronc stable et 2. La production devrait contenir des BINAIRES testés ST, UAT et Régression (pas seulement source - pensez CC.)

Cela nous a amenés à concevoir une stratégie qui est un hybride entre les stratégies basées sur les fonctionnalités et les versions SC.

Nous avons donc un coffre. À chaque sprint, nous dérivons la branche de sprint (pour les personnes non agiles - un sprint n'est qu'un effort de développement temporel avec une sortie variable en fonction de la complexité.) À partir de la branche de sprint, nous créons les branches de fonctionnalité et le développement parallèle commence en elles. Une fois que les fonctionnalités sont terminées et testées par le système, et que nous avons l'intention de les déployer, elles sont fusionnées dans la branche de sprint - certaines peuvent flotter sur plusieurs sprints, généralement les plus complexes. Une fois que le sprint est proche de sa fin et que les fonctionnalités sont terminées ... nous "renommons" la branche de sprint en "régression" (cela permet à CruiseControl de la récupérer sans aucune reconfiguration), puis les tests de régression/intégration commencent sur le cc-build OREILLE. Quand tout est terminé, il entre en production.

En bref, les branches basées sur les fonctionnalités sont utilisées pour développer, tester le système et la fonctionnalité UAT. La branche sprint (en réalité la branche release) est utilisée pour fusionner sélectivement les fonctionnalités à la demande et le test d'intégration.

Maintenant, voici une question à la communauté - nous avons évidemment du mal à effectuer une intégration continue en raison du fait que le développement se produit sur de nombreuses succursales et la surcharge de reconfiguration de CruiseControl. Quelqu'un peut-il suggérer et conseiller?

1
XAvatar

Dave Farley , un auteur de Continuous Delivery , désigné Trunk Based Development (TBD) comme la pierre angulaire de l'intégration continue (CI) et de la livraison continue (CD). Il dit:

Toute forme de ramification est contraire à l'intégration continue.

Il dit aussi:

La fonctionnalité de branchement est très agréable du point de vue d'un développeur individuel mais sous-optimale du point de vue d'une équipe. Nous aimerions tous pouvoir ignorer ce que tout le monde fait et continuer notre travail. Malheureusement, le code n'est pas comme ça. Même dans des bases de code très bien factorisées avec une belle séparation des préoccupations et des composants merveilleusement couplés de manière lâche, certains changements affectent d'autres parties du système.

Trunk Based Development (TBD) est la pratique consistant à intégrer les modifications de code dans le tronc (a.k.a, master, mainline) au moins une fois par jour - de préférence plusieurs fois par jour. L'intégration continue (CI) est une pratique similaire, sauf qu'elle implique également de vérifier les modifications du code à l'aide de tests automatisés. La meilleure stratégie de branchement pour cela est de travailler directement à partir du tronc et d'effectuer des révisions de code via Pair-Programming . Si, pour une raison quelconque, vous ne pouvez pas vous jumeler ou si vous voulez vraiment créer une branche, assurez-vous que vos branches sont de courte durée (moins d'une journée).

Je travaille sur Trunk, "master" dans mes repos GIT. Je m'engage à maîtriser localement et à pousser immédiatement, lorsque je suis en réseau, vers mon référentiel maître central où CI s'exécute. C'est ça!

Pour les grandes fonctionnalités (c'est-à-dire celles qui prennent plus d'une journée), essayez de les diviser en petits morceaux de logique qui peuvent être intégrés dans le coffre sans casser le logiciel. Vous pouvez également utiliser des techniques telles que marquage des fonctionnalités et ramification par abstraction qui vous permettent de déployer un travail incomplet sans affecter les utilisateurs finaux.

J'utilise branch par abstraction, dark-releasing et parfois feature-flags. Ce que j'obtiens en retour est un retour rapide et définitif (au moins sur la qualité de mes tests).

0
Yani

La façon dont je le vois, vous voulez avoir un ensemble limité de branches où vous pouvez vous concentrer. Puisque vous voulez des tests, des métriques de qualité de code et de nombreuses choses intéressantes à exécuter avec les builds, avoir trop de rapports vous fera probablement manquer des informations.

Quand et quoi brancher, cela dépend généralement de la taille de l'équipe et de la taille des fonctionnalités développées. Je ne pense pas qu'il existe une règle d'or. Assurez-vous que vous utilisez une stratégie où vous pouvez obtenir des commentaires tôt/souvent, et cela inclut la qualité impliquée dès le début des fonctionnalités. Le bit de qualité signifie que lorsque vous automatisez au fur et à mesure que l'équipe se développe, si vous vous branchez sur un grand ensemble de fonctionnalités qu'une équipe construit, vous devez également impliquer la qualité dans l'équipe.

ps Où avez-vous obtenu ces références d'approche? - ne pense pas que ces graphiques représentent toutes les options

Mise à jour 1: Expliquer pourquoi j'ai dit que ce n'était pas une règle d'or. Fondamentalement, pour les équipes relativement petites, je l'ai trouvé préférable en utilisant une approche qui est un mélange. Les branches d'entités sont créées si elles sont longues et une partie de l'équipe continuera d'ajouter de plus petites entités.

0
eglasius