VisualStudioTFS分支和合并指南自从2006年组建以来,VisualStudioALMRangers团队就一直在Microsoft开发事业部工作,旨在促进VisualStudio产品组、Microsoft服务与Microsoft最有价值专家(MVP)社区间的协作。Rangers团队通过解决功能缺失问题以及消除阻碍产品采用的因素,实现他们的基本目标宣言:“通过为缺失的功能或指南提供带外解决方案来加速VisualStudio的采用”。借助各种技术专家和业务专家之间的合作,Rangers通过共享实际经验来为社区提供强大支持。(如需了解有关Rangers的更多信息,请访问msdn.microsoft.com/vstudio/ee358786。)VisualStudioTeamFoundationServer(TFS)分支指南2010(tfsbranchingguideiii.codeplex.com)通过提供从社区学习到的实际动手实验和课程,将使用VisualStudioTFS2010进行分支与合并方面的富有深刻见解的实际指南进行了整合。在本文中,我们将为您介绍我们正在为下一版指南而制定的一些高级分支方案。分支:“当前情况”Rangers分支指南是在VisualStudio2005和TFS2005发布之后作为一个Rangers项目而开始的。Rangers指南是于2007年在CodePlex上首次发布的。2008年,Rangers启动了分支指南II项目。在第二次发布中,我们将该指南重新组织为一组相关文档(“主要内容”、“方案”、“问题与解答”、“图表”、“海报”等)。第二批文档中的每个文档都建立在主分支文档中提出的初级指南之上。Rangers分支指南II是于2008年下半年在CodePlex上发布的。2009年,Rangers团队再次启动了一个新的分支指南项目:分支指南2010。第三次发布的分支指南侧重于展示VisualStudio2010和TFS2010中的许多新的分支功能。2010版中的一个重要新增功能就是分支可视化。可能由于我们将最新版本命名为“RangersVisualStudioTFS分支指南2010”,因此造成用户误认为该指南只适用于VisualStudio2010。我们希望澄清的是,2010指南文档中展示的最佳实践与指南仍适用于早期版本的VisualStudio和TFS。事实上,Rangers团队已经从使用其他工具进行源代码控制管理(SCM)的人员那里获得积极的反馈。2011年,Rangers团队将再次计划对Rangers分支指南进行一次更新。您可随时在CodePlex网站发布疑问、中肯的反馈或关心的问题。分支目标和策略分支的一个主要目标是在并行工作流之间提供隔离。在当前的Rangers分支指南2010中,我们更侧重于版本隔离而不是复杂开发计划中的隔离。在许多情况下,某种产品下一个版本的所有开发活动都可由单一开发团队来完成。在这种简单情况下,只需要一个开发分支就可以将开发工作与不断进行的稳定化(主分支)或持续的工程设计(交付产品版本,带有不断进行的修补程序和服务包支持)隔离开。Rangers常常被问到有关为更加复杂的开发方案提供支持的问题,在这种开发方案中,单一的开发分支无法针对较大型的产品开发工作提供足够的灵活性或隔离。在Rangers分支指南的下一个版本中,我们将在复杂开发方案(例如功能团队开发)方面增加更多的说明。我们希望将分支策略讨论分为两个方面:我的组织如何开发软件?我们是否需要一个更小、更简单的团队结构,或者我们是否需要对进行并行开发工作的更多复杂团队提供支持?我的组织如何向其客户(不管是内部还是外部客户)发布软件?我们是否需要对多个已发布的版本提供支持?我们是否需要提供修补程序或服务包?在某些情况下,组织的发布策略可能影响开发过程,尤其是开发团队的结构。但在很多情况下,发布过程和分支策略的复杂性可能与开发过程和分支策略的复杂性无关。在设计一种分支策略时,不仅要考虑分支结构,而且还要考虑分支过程。例如,在Rangers分支指南2010所描述的基本分支计划中,只有三种分支(主分支、开发分支和发布分支)。一个良好的分支策略将会描述分支关系(例如,主分支是开发分支和发布分支的父分支)。另外,一种分支策略应该描述该分支结构所必然需要的过程。例如,在主分支中生成代码的频率如何?从主分支向开发分支合并代码(正向集成)的频率如何?从开发分支向主分支合并代码(反向集成)的条件是什么?(等等)让我们讨论一些典型的分支方案。功能团队方案组织经常需要采用一种分支策略,为需要多个开发团队或功能团队并行工作的大型、复杂的开发活动提供支持。这样就产生了需要多少个单独的开发分支的问题。如果我有多个开发分支,我该何时以及如何将一个团队开发的功能与其他团队开发的功能进行集成?这些问题的答案应体现在一个开发分支策略中。让我们首先介绍一种复杂的开发方案。虽然整个方案可能有一个共同的发布计划,但可能会有多个功能团队分别致力于实现独立的里程碑。这些功能在完成并经过测试后将被集成到主分支之中。在一个团队中,各个开发人员都使用局部工作区将所做更改与团队中其他人的更改进行隔离。要将一个功能团队所做的更改与针对同一产品并行工作的其他团队所做的更改进行隔离,功能团队分支提供了一种良好的方法。如果没有这种功能团队隔离,则由一个团队所做的更改可能会带来将影响其他团队速度的重大变化。创建用于功能团队隔离的分支结构相对简单。但是,我们首先需要计划以后对功能团队分支进行集成的方式。我们是否要像图1所示那样,在主分支与功能团队分支之间添加一个“集成分支”?图1主分支和集成分支或者,我们是否要取消集成层而以另外一种方式来集成功能团队更改?最佳实践建议是什么?我们建议尽量减少分支层次结构中的层次数目。在主分支和功能团队分支之间添加一个集成层之后,实际上将在主分支和功能团队分支之间移动更改所需的合并工作加倍了。分支有助于隔离更改,但分支的代价是需要在各个分支之间合并代码,并需要解决避之不及的合并冲突。添加集成层会将合并工作加倍,并且可能也将解决合并冲突的工作量加倍。如果取消集成层,就可以将分支层次结构中的层数减少。但是,功能团队1与功能团队2的集成将在哪里进行?将在哪里对集成进行测试?为了使主分支尽可能保持稳定,请避免向主分支中引入未经测试的集成更改。在没有集成层的情况下,功能合并和集成测试必须以可控的方式在功能团队分支自身内部完成。建议在主分支(稳定分支)中执行日常生成,并在一个良好的日常生成之后,执行从主分支到开发(功能)分支的合并。在功能分支中的代码相对稳定之前,请不要将代码从功能分支合并回主分支。换言之,功能分支应通过质量保证大门才能与主分支合并。只有当功能分支中的代码被认为“已准备好发布”或“已准备好与其他团队共享”时,我们才能考虑将此功能分支与主分支或其他功能分支集成。图2说明了每个“已准备好发布”里程碑之后的这一过程。图2功能分支下面是处理步骤:将功能团队1分支与主分支合并之前,执行从主分支到功能团队1分支的一次最终合并(正向集成,即FI)。完成对主分支中的代码与功能团队1分支中的代码进行集成的最终测试。在功能团队1分支中的代码稳定之后,将该代码合并回主分支(反向集成,即RI)。此时,主分支中的代码将与来自功能团队1的代码合并。在主分支中执行等同于日常生成的生成与测试。在下一次成功生成主分支时,将主分支合并到每个功能团队分支。最初,这会导致功能团队1中的代码与功能团队2中的代码合并。在功能团队2分支中,测试功能团队1代码与功能团队2代码的集成。当功能团队2代码准备好发布或准备好与其他团队共享时,将功能团队2代码合并回主分支。但首先要执行一次从主分支到功能团队2的最终合并,并测试最终集成。注意:省略单独的集成层的一个关键要求是能够对集成进行自动化测试。在团队致力于识别和解决在将很多更改合并到一个分支的过程中产生的Bug时,自动化测试有助于降低对代码速度(也就是功能团队工作效率)的影响。如果不能对集成更改进行自动化测试,所存在的风险是功能团队的代码速度会受到不利影响,因为他们需要执行手动测试来识别和解决Bug。在这种情况下,组织可能会考虑在主分支和功能分支之间添加一个集成层。如前所述,集成层可能会导致合并以及解决合并冲突工作的增加。但其益处是,有了这个层之后,集成对功能团队的代码速度产生的影响较小。良好的分支策略需要有健全的分支结构以及健全的分支过程,这样才能确保功能团队获得最高代码速度,同时保持主分支的稳定性。公共代码共享方案在项目之间共享公共代码对于很多组织来说都是一种挑战。在VisualStudio中,共有三种用于在项目之间或解决方案之间共享代码的主要方法:文件链接二进制(程序集)共享源代码共享正如我们在本文中别处所述,还有多种用于代码隔离的方法:团队项目隔离分支隔离工作区隔离为组织选择正确的代码共享策略可能涉及将代码共享方法与隔离方法进行组合。文件链接:这是VisualStudio的一项功能(“添加现有项”),其中,多个项目可以共享对同一源文件的引用。文件链接更适合所共享的文件数目有限的小型项目。(这类似于VisualSourceSafe中的文件共享。)采用文件链接时,将仅保留所链接的源文件的一个版本。对链接文件所做的更改会立即被与该文件链接的所有项目接受。文件链接的缺点在于,对链接文件进行的更改应与所有相关项目团队进行协调。甚至经过仔细协调的更改也可能引起相关项目中的重大更改。二进制共享(程序集引用):在二进制共享中,一个VisualStudio解决方案将通过程序集引用来引用共享代码。此时,生成或编译相关解决方案并不会同时编译公共的共享源代码。与使用项目引用相比,使用程序集引用来编译相关项目的速度将更快。拥有公共代码的团队具有完全的所有权和控制权,在理论上,这意味着产品的控制、版本控制和质量或许会更佳,并会避免分支和合并的复杂性。由于重复使用公共代码的团队不能访问公共源代码,所以他们依赖于拥有公共源代码的团队来添加新的功能并解决公共共享代码中的Bug。用于公共代码的程序集可通过复制到一个人所共知的文件共享中而得到共享,而该文件共享可由相关项目来引用。可能需要将签名程序集添加到全局程序集缓存中。或者,可将程序集从公共代码团队项目复制到相关项目主分支下的一个bin文件夹中。源代码共享:通过VisualStudio中的源代码共享,相关项目可针对公共共享代码使用项目引用。生成解决方案时,将生成所有项目,包括公共共享代码项目。对于复杂项目,如果具有很多对共享代码的项目引用,则可能会显著增加生成时间。在这种情况下,将由一个团队在其自身的TFS团队项目中拥有和管理公共共享代码。若要共享此公共代码,首先要将代码分支到含有占用(相关)项目的团队项目的文件夹中,如下所示:在相关项目的团队项目中,创建一个名为“Share”的文件夹(例如,$\Product1\Share)。将公共库(例如EnterpriseLibrary)的Main分支分支到相关项目的Share文件夹中,例如,将$\EnterpriseLibrary\Main分支到$\Product1\Share\EnterpriseLibrary中。将相应公共代码项目添加到相关项目的解决方案。创建从相关项目到解决方案中现有公共代码项目的项目引用。注意:TFS2010中不支持嵌套分支。如果您尝试执行的分支操作会导致在文件夹结构中的现有分支之上或之下创建新分支,则可能会发生嵌套分支错误(请参见图3)。图3在TeamFoundationServer2010中引起错误的嵌套分支的示例您的组织需要决定是否应在每个相关项目中允许对公共共享源代码进行更改。为防止更改,可在从公共库分支之后将新分支设置为只读。随后,必须在公共库团队项目中完成对公共代码源的所有更改,然后将更改合并到相关项目的团队项目中。或者,可对相关团队项目中的共享代码源进行更改。可以将这些更改(通过反向集成)合