TFS: fusionner les meilleures pratiques
nous avons une architecture de branche standard où nous avons une branche de développement pour chaque équipe, une branche d'intégration commune (à partir de laquelle toutes les branches de développement sont ramifiées) et branche de production ramifiée à partir de L'intégration.
pendant la phase de développement, je fais beaucoup d'engagements dans la direction du développement. A la fin de la phase je fusionne mes changements à l'intégration et plus tard à la production.
est-il logique de fusionner chaque propagation individuellement, en copiant description initiale de l'engagement et le lien à la tâche originale? Une autre option est bien sûr de fusionner toutes les propagations à la fois, avec une seule opération de fusion. La raison de ma question est que la première méthode prend beaucoup de temps. Je ne vois aucun outil d'automatisation dans TFS qui lierait la fusion dans une autre branche à la propagation originale.
j'aimerais connaître votre opinion sur les meilleures pratiques.
2 réponses
- Fusions à partir de Dev * - > intégration et intégration - > la Production doit toujours être une "copie" de fusions. C'est le moyen le plus sûr pour préserver la stabilité de vos branches en aval.
- première fusion dans l'autre sens (par exemple intégration -> Dev2) pour récupérer les dernières modifications de la branche cible.
- s'il y a des conflits, Gérer les diffs au cas par cas. AcceptMerge (soit auto ou manuel) est généralement le résultat désiré, mais parfois vous voulez prendre l'un ou l'autre branche de la copie inchangé.
- Utilisez la branche source (Dev #2 dans notre cas) pour intégrer complètement ces changements, y réagir et les stabiliser.
- fusionner dans la direction désirée (par exemple Dev2 -> intégration). Résoudre tous les conflits comme AcceptTheirs [alias "copier à partir de la source"].
- S'assurer qu'il n'y a aucun changement dans la Direction générale cible entre l'étape #1-4. Si la branche de Dev accepte les fusions tôt et souvent, comme il devrait être, alors il ne devrait pas être lourd pour verrouiller la branche cible pendant ce processus-si tout va bien-court. Si vous prévoyez un" big bang " fusion de la mort pour une raison quelconque, Il ya une chance décente verrouillage empêchera les autres équipes de faire la même chose en parallèle, de sorte que vous pouvez avoir à itérer à travers les étapes #1-4 à plusieurs reprises jusqu'à ce que vous êtes prêt.
- faire des fusions "de rattrapage" chaque fois que c'est possible. C'est, de fusionner les choses dans l'ordre où ils ont été enregistrés. Si les changements 10, 20, et 30 sont des candidats à fusionner à partir de A - > B, puis n'importe laquelle de ces gammes de fusion est un " rattrapage:" 10~10, 10~20, 10~30. Toute gamme changeset qui saute #10 est connue sous le nom de " cherry pick."Une fois que vous commencez la cueillette de cerises, vous rencontrez quelques dangers:
- Vous ne pouvez pas utiliser le fusionner vers le bas, la copie modèle décrit ci-dessus. Rien que pour ça, Laura Wingerd dirait que tu sautes par-dessus un trottoir.
- si l'un des fichiers touchés dans votre zone a aussi été touché précédemment, vous devrez faire un contenu à 3 voies fusionner de manière à ce que seuls les dif cueillis soient propagés. Aucun outil de diff n'est parfait; vous ajoutez un risque non nul d'apporter plus de code que prévu, écrasant accidentellement les modifications apportées à la cible, introduisant des bogues logiques là où les deux branches divergent, etc.
- l'ensemble des changements que vous promouvez dans la branche supposée plus stable représente une configuration qui a jamais ont été construits ou testés auparavant. Vous pouvez faire une bonne estimation sur la finale l'état de la branche cible. "Je fusionne tous les changements affectant le Module Foo, et j'ai testé la nouvelle version de Foo dans Dev, donc C'est comme ça que Foo se comportera dans L'intégration, Non?" Assurer...peut-être...si vous pouvez suivre chaque dépendance dans votre tête (y compris tout ce qui peut avoir changé dans L'intégration pendant que vous testiez Dev). Mais ces suppositions ne sont en aucun cas connues ou validées par votre chaîne D'outils SCM.
- dans TFS en particulier, la sélection de cherry où les changements d'espace de noms sont impliqués est en train de demander à être brûlé. Si la portée de votre version et / ou la portée de votre chemin excluent la source d'un renommage, il s'agira plutôt d'une branche. Si vous excluez la cible, il y aura une suppression. Si votre chemin n'inclut pas la racine d'un undelete, vous obtiendrez des erreurs cryptiques. Si votre intervalle de temps s'étend entre un undelete & re-delete, vous obtiendrez des fichiers "fantômes" apparaissant dans la cible même si vous n'incluez pas l'undelete lui-même. Si vous fusionnez Moves avec tous vos scopes path & version correct, mais le faire hors de l'ordre, il est possible de finir avec un nom de cible différent que le nom source, même après que tous les candidats ont été changesets épuisés. Je suis sûr qu'il y a d'autres moyens pour que ce combo tourne mal qui ne viennent pas à l'esprit en ce moment...fais-moi confiance.
- toujours faire un Get sur la branche cible avant de fusionner. Version avancée pour la sécurité ultime: synchroniser l'espace de travail où vous fusionnerez avec un numéro de série de modifications spécifique qui est à ou proche la pointe, puis aussi [rattrapage] fusionner à ce même ensemble de modifications. Ceci permet d'éviter quelques problèmes potentiels:
- Fusion EN code périmé, donnant des diffs 3-way déroutants qui semblent supprimer change de ce qu'on voit à l'Extrémité. [vous éventuellement les récupérer à l'Arrivée + le Résoudre, mais pas de raison de passer par deux risqué de diff lorsque vous pouvez éviter à la fois l']
- devoir passer par le processus de résolution des conflits deux fois: une fois sur Merge, une fois sur Checkin. Il n'y a aucun moyen de évitez cela dans le cas général, mais la plupart du temps le nombre de changements simultanés effectués pendant que vous fusionnez + résoudre est minuscule par rapport au nombre de changements que vous rencontreriez dans un espace de travail qui pourrait être des jours ou des semaines hors de date.
- ne fusionnez pas par étiquette (ou espace de travail) à moins que vous ne sachiez vraiment ce que vous faites. Passons en revue les fonctionnalités offertes par les labels TFS et analysons pourquoi chacune est inappropriée pour une fusion sûre et cohérente.
- les Étiquettes peuvent représente plusieurs points dans le temps. Si une étiquette représente un instantané cohérent de la CVS -- et a toujours été prévue comme telle -- alors elle n'a pas de technique avantage sur une date ou un numéro de changement. Malheureusement, il est assez difficile de dire si une étiquette est en fait cohérente dans le temps. Si non, la fusion par l'étiquette peut conduire à:
- sélection par inadvertance, si la gamme commence par une étiquette qui pointe vers un article @ une fois en avance sur son premier candidat
- exclusion par inadvertance, si la gamme commence par une étiquette qui pointe vers un article @ un temps avant la fin de la gamme
- exclusion par inadvertance, si la fourchette se termine par une étiquette qui pointe vers un article @ un moment avant le début de la fourchette
- Les versionspecs D'étiquette représentent un ensemble spécifique d'articles. Ils peuvent être utilisés pour exclure délibérément des fichiers et des dossiers qu'une simple requête récursive verrait autrement. Cette fonctionnalité est aussi une mauvaise correspondance pour les opérations de fusion. (Et encore, si vous ne pas besoin de cette capacité,vous courez le risque suivant sans rien gagner sur les dates et les changements.)
- les éléments non présents dans l'étiquette seront simplement ignorés, plutôt que fusionnés en tant que suppressions en attente. Contrairement à certains des cas de bordereaux couverts jusqu'à présent, il s'agit d'une grosse affaire qui est très susceptible de se produire dans les scénarios traditionnels, mais la plupart des gens manquent. [En conséquence, TFS 2010 ajoute la prise en charge des éléments supprimés à l'intérieur étiquette.]
- cueillette de cerises par inadvertance, si vous ajoutez à l'étiquette un article qui est présent depuis un certain temps mais qui a été exclu des fusions précédentes en raison de l'un des effets secondaires mentionnés ci-dessus.
- cueillette intentionnelle de cerises. L'avantage que cette fonctionnalité apporte à la fusion est de briser une de nos lignes directrices, donc évidemment ce n'est pas une bonne raison du tout. En outre, il provoque la cueillette de cerises à la le fichier niveau, qui est encore plus dangereux que "ordinaire"" la cueillette de cerises par changeset.
- Les étiquettes ont des noms, des propriétaires et des commentaires personnalisables. Ainsi, nous avons une différence d'utilisabilité pure par rapport aux dates/séries de changements; aucun avantage technique n'est conféré. Mais même ici, ce n'est pas aussi attrayant que ça en a l'air. TFS ne fait pas grand chose pour faire réellement surface des étiquettes dans L'interface utilisateur, alors que vous pouvez voir les commentaires changeset partout. La recherche par le propriétaire est rapide( côté serveur), mais la plupart des autres recherches sont lentes (côté client) à moins que vous connaître précisément le nom de l'étiquette. Installations de gestion sont pratiquement inexistants. Pas de changelog ou d'audit, juste une estampille temporelle. En tout, ce sont à peine des raisons d'abandonner la caution fournie par les révisions.
- les Étiquettes peuvent représente plusieurs points dans le temps. Si une étiquette représente un instantané cohérent de la CVS -- et a toujours été prévue comme telle -- alors elle n'a pas de technique avantage sur une date ou un numéro de changement. Malheureusement, il est assez difficile de dire si une étiquette est en fait cohérente dans le temps. Si non, la fusion par l'étiquette peut conduire à:
- toujours fusionner la branche entière à la fois. Il est parfois tentant de fusionner des fichiers ou des sous-Fichiers, mais cela revient en fin de compte à une simple sélection sous un nouveau prétexte.
- Planifier à l'avance. Malheureusement, re-parenting branches dans TFS est un sujet douloureux. Parfois c'est ardu, parfois c'est seulement quelques pas, mais c'est jamais évident; il n'y a pas de commandement construit (jusqu'en 2010). Cela nécessite une connaissance assez approfondie de la structure actuelle de votre branche, de la structure désirée et de la façon d'abuser des effets secondaires de diverses commandes TF.
- Ne créez pas de branches à l'intérieur des branches. Par exemple, il est parfois recommandé de brancher et de fusionner pour maintenir des modules ou des binaires communs entre des modules à couplage lâche. projet. Je ne pense pas que ce soit un très bon conseil pour commencer -- bien mieux de faire en sorte que votre système de construction fasse son travail principal correctement, que d'obliger votre système de contrôle des sources à faire quelque chose qu'il n'est pas vraiment conçu pour faire. Quoi qu'il en soit, cette tactique de "partage" entre terriblement en conflit avec les projets eux-mêmes vivent à l'intérieur d'une hiérarchie de branche plus large aux fins de la GCA. Si vous n'êtes pas uber prudent, TFS vous laissera volontiers créer des relations arbitraires entre plusieurs branches entre les éléments de contrôle de version. Bonne chance pour régler ça (j'ai déjà dû le faire pour un client, pas jolie.)
- Ne créez pas des fichiers avec le même chemin relatif dans deux branches indépendamment; utilisez la fusion pour les relier ou vous passerez des heures à chercher des conflits d'espace de noms. (n/d en 2010)
- Ne pas ajouter de fichiers en haut d'un chemin où d'autres éléments existaient auparavant. Que les anciens articles aient été renommés / déplacés, ou simplement supprimés, vous allez faire face à des défis intéressants au moment de la fusion; au minimum, il faudra deux Archivages pour pleinement se propager. (n/a en 2010, bien que l'expérience soit encore quelque peu dégradée; seulement 1 checkin est nécessaire, le contenu de l'article est préservé, mais l'histoire du nom est dans cette branche et toutes les branches en aval)
- N'utilisez pas le drapeau /force sauf si vous savez ce que vous faites. Toutes les fusions / forces sont effectivement des coups de pioche, conduisant à des risques très similaires (perte de code pendant le processus de résolution, etc.).
- N'utilisez pas le drapeau /sans fondement à moins que vous n'utilisiez vraiment savez vraiment ce que vous faites. Vous manquez supprime, comme les étiquettes, sauf que renomme toujours se Morpher en branches au lieu de simplement dans les cas de bord malchanceux. Vous n'obtenez aucune protection de débit/crédit que ce soit. Et le plus effrayant, c'est que vous allez créer de nouvelles relations de branche. Parfois. (aucun retour d'information n'est montré à l'utilisateur quant à savoir si chaque élément cible est nouveau, ancien avec une nouvelle relation, ou ancien avec une relation existante)
- Éviter / jeter (et, de manière équivalente, accepter nos résolutions) lorsque cela est possible. Rejeter certaines modifications pour n'en accepter que d'autres est un autre nom pour "cherry-picking":)
- soyez prudent avec vos résolutions en général. Chacun a des effets en aval uniques en dehors de son effet sur la fusion à portée de main.
- Acceptttheirs est un moyen rapide et puissant pour obtenir une "copie" fusion, comme préconisé dans la première ligne directrice. Si vous l'utilisez dans d'autres scénarios ainsi, rappelez-vous que vous êtes juste dire à TFS de rendre le contenu du fichier identique. Vous lui dites que les deux fichiers sont complètement synchronisés à partir d'une gestion des versions POV. En d'autres termes, tout changement antérieur au fichier cible qui pourrait avoir fusionné dans la direction opposée ne sera plus considéré comme un candidat une fois que vous aurez vérifié son acceptation.
- notez qu'un AcceptMerge (auto ou manuel) dont le contenu résultant est identique au fichier source sera considéré comme un Acceptttheirs par le serveur. Il n'y a pas de différenciation dans le protocole de Checkin webservice.
- en utilisant AcceptYours quand les renom sont impliqués peut tordre votre cerveau. Vous vous retrouverez rapidement dans une situation où "le même" article a des noms différents dans différentes branches. En supposant que vous avez une bonne raison de rejeter les changements en premier lieu, ce phénomène n'est pas dangereux en soi -- en fait, il est probablement nécessaire d'éviter soit de construire des pauses ou des personnalisations uniques à vos makefiles. C'est juste déroutant pour les humains, et très susceptible de casser tous les scripts d'automatisation que vous avez qui supposent des structures d'arbre sont cohérentes d'une branche à l'autre.
- AcceptMerge est la valeur par défaut pour une raison. Il conduit parfois à plus de conflits de version qu'il ne semble strictement nécessaire, mais c'est le choix le plus sûr lorsque la vraie Fusion est nécessaire. (P. ex. étape n ° 1 de la ligne directrice principale "Fusionner vers le bas, copier vers le haut".) Aussi longtemps que vous suivez les lignes directrices, le nombre de fusions qui nécessitent manuel l'attention devrait tomber -- de façon spectaculaire donc si vous venez d'un flux de travail qui est lourd sur la cueillette des cerises.
- les bogues doivent être liés à l'ensemble des changements où la correction a été effectuée. Si vous devez plus tard percer dans les branches en aval pour voir quand, où (et peut-être comment) le bugfix a été propagé, c'est une fonction de contrôle purement source. Pas besoin de polluer l'objet de travail avec un bagage supplémentaire, encore moins de modifier la façon dont vous effectuez fondamentalement les fusions. Dans 2005/2008 vous pouvez parcourir l'histoire de la fusion avec la commande 'TF merges' ou une interface utilisateur de tierce partie telle que Attrice SideKicks. En 2010, vous obtenez des visualisations astucieuses intégrées dans Visual Studio. Instructions et des captures d'écran sur le site MSDN.
j'ai toujours seulement fusionné une gamme de propagations dans la branche d'intégration, en spécifiant seulement la gamme des changesets que j'ai fusionnés.
les éléments de travail liés à chaque élément de travail à l'étape de l'élaboration sont des éléments de travail à l'étape de l'élaboration. Je ne pense pas qu'il soit besoin de rouler sur l'intégration ou la libération.
vous n'avez pas précisé où vous enregistrez les bogues / demandes de fonctionnalités des clients. Si vous assignez ceux-ci à la branche de libération vous êtes il est probable que vous créez d'autres éléments de travail plus détaillés pour la branche développement et que vous marquerez simplement tous les problèmes résolus par les corrections de bogues pour la branche dans laquelle vous fusionnez.
Donc en résumé je ne vois aucune raison de ne pas aller avec le volume des fusions.