为发行版选择正确的分支策略


11

从新项目的新开发团队开始,我们必须为源存储库(例如Microsoft Team Foundation Server 2010)定义分支策略。关于是否要...我们进行了激烈的讨论。

。有一个Release分支,我们可以从中进行生产构建,然后在实际发布某些内容时添加Label

要么

。每个投入生产的新版本都有一个新的Release分支(例如,版本1、2、3等

选项A看起来很简单,但是我们不确定从长远来看是否会导致问题。选项B似乎只是创建了许多长期存在的分支,并且随着时间的推移不断积累。

有人有任何经验可以帮助我们做出决定吗?具体来说,我想听听任何一种选择的痛点所在。随时提供有关TFS和/或发布管理含义的特定经验。

Answers:


15

选项A:仅使用主线并标记发布

优点:

  • 您避免合并地狱。
  • 保持主线鼓励一些最佳实践,例如适当的发布计划,不引入大量WIP,使用抽象分支来处理带外长期工作,以及使用开放式封闭系统和可配置功能来管理工作可能进行中 可能不会;现在或将来需要禁用此功能,以释放或避免完全回滚。

缺点:

  • 处理进行中的作品成为一个问题,并在发布时增加了潜在的地面攻击区域。但是,如果您的开发人员受过严格训练,那么新功能应该是可配置的和模块化的,因此很容易禁用/启用,或者没有WIP,并且在每个发布点所有工作都已完成或尚未开始(即Scrum)。
  • 大规模/带外更改需要提前进行更多思考以实现(例如,通过抽象进行分支)。

我个人更喜欢这种方法。代码覆盖率和单元测试应该识别尚未准备就绪的代码,并且人们不应该使用当前迭代期间不会发布的代码。通过抽象或其他机制进行的分支可用于处理长期更改和正在进行的工作。

当您不这样做时,您会发现自己正在处理合并问题,过时的代码,永远不会发布的功能等。

选项B.按发布分支

优点:

  • 您可以开始进行下一个迭代,而当前的迭代将完成其验收测试。
  • 我还不确定其他东西。

缺点:

  • 吨的分支机构。
  • 仍然需要在发布点标记分支。
  • 仍然需要处理WIP并将WIP从上一发行分支合并到下一个发行分支,如果这不可行的话,仍然需要禁用或猛拉发行分支并重新运行验收测试
  • 修补程序需要应用于更多分支(发行分支+修补程序+新标签+将修补程序合并到vnext分支中,并可能根据修补程序的位置将其合并到vnextnext中。)

我不是这个解决方案的忠实支持者^ _ ^。

通常,我建议您只尝试坚持主线。如果您的开发人员在编写WIP时遇到麻烦,当WIP在剪切失败时很容易被取消,或者在下一个版本的早期检查过,那么您可以开始讨论在代码应该完成和分支的地方标记代码。如果有必要,请从此处解决开发人员单元测试未能捕获的被忽略的缺陷和错误。

理想情况下,尽管我认为您希望将其作为例外流程,而不是规则。

选项C.疯狂红利选项

如果您想花哨的话,还可以考虑按用户故事/按功能分支模型。(在TFS或任何非DVCS中,这是一个可怕的想法,同时,如果使用git或mercurial这样的DVCS,则实现起来非常困难)。

在过去,我为以前的雇主维护团队实施了以下内容,该团队使用的旧代码库无法轻松地从svn移植到商业软件。要满足始终可释放的主线的业务需求,需要进行大量不必要的工作,而不仅仅是更好地协调发布。。。

  1. 功能由开发人员在其团队的dev分支中开发。
  2. 当某项功能准备好供同行评审时,开发人员将其捆绑在一起,形成一个从Dev分支到CR分支的合并,并在标题中包含功能ID /用户故事。*由预提交挂钩强制*
  3. 通过CR后,将使用管理工具将功能升级到QA分支。(我编写了一个小终端应用程序,列出了各个接受阶段中存在的用户案例,并允许操作员在这些接受阶段之间对其进行升级或降级)
  4. 质量检查会运行自动化和手动可用性测试。如果功能良好,则将其推入发布分支(主线)。如果该功能被拒绝,则其降级/还原出QA分支,直到开发人员可以解决测试过程中提出的问题并向CR分支添加提交补丁为止。
  5. 如果从QA分支还原了代码并应用了修复程序,则终端工具将重新应用必要的更改,以将功能从CR分支带回到QA分支,以便QA可以重新审阅代码并提升代码或再次降级。
  6. 在任何时候,释放分支都应处于稳定的可释放状态。
  7. 发布后,将从主线中纺出新的Dev,QA和CR。

@Keith_Brings这是一个非常不错的摘要,谢谢。正如您已经指出的那样,因为我正在使用TFS,所以选项C并不是真正的选项,但是仍然很有趣。
JoeGeeky 2012年

我看不到选项A如何工作。在我公司,我们为不同的客户提供不同的版本。如果我们仍在1.0版上进行功能/修补程序开发,并且还在积极地开发2.0版甚至3.0版,则不能在一个分支上完成所有这些工作。也许由于您的发布模式,您可以享受选项A的奢华。但是,这不是每个人的发行模式,对于我们这些坚持了功能蔓延或多个并行的版本中,我们必须使用选项B.
void.pointer

6

我们推出的每个发行版都有单独的分支机构(每年约4个)。当您需要拉特定的版本时,这非常方便。

如果您需要维护几个较旧的版本,则我认为标记不会起作用。使用特定的发行分支,您可以将修补程序分别应用于每个分支(或对其进行选择),而不必担心其他发行版。

当您寻找引入错误或功能时,也使比较发行版本变得容易得多。

不必担心分支的数量或分支不经过更改的时间。版本控制系统可以控制您并提供项目开发的历史记录。历史有不会改变的趋势……而且不用担心您的简历无法应对。我们在一个开发分支中使用Perforce 9000+个文件,对于我们正在处理的发行版,最多使用50个开发分支,并且如上所述,每个发行版使用一个分支。Perforce甚至没有呼吸困难。

简而言之:简化您作为开发人员/维护人员/错误修复程序/问题猎人的生活,不必担心分支数量或文件数量。任何自重的简历都会应付。

编辑:

关于分支机构的数量,我们完全不会感到困惑。我们对发布分支的命名方案和对开发(或工作)分支的第1期1分支策略可能与此有关。

发布分支以其持有的发布命名,即:发布2011 Service Pack 1的R2011SP1。我们的工作分支的智能名称较少:sub01,sub02,sub03等。“ sub”来自所有工作分支都是sub分支的事实验收分支机构。接受分支是收集所有准备发布的问题的分支。

我们的第1期1工作分支机构政策,再加上我们的问题跟踪系统已通过“分支”字段进行了自定义,这一事实确保了我们始终知道在哪个分支中发生了什么问题。将问题集成到接受分支中后,将更新此字段。这意味着我们始终知道哪些问题可以发布(一旦完成验收测试)。同样,在创建发行分支时,我们会更新此字段,这样我们就可以始终跟踪发行问题的发行版本。


1
我相信您可以从TFS中的标签分支。因此,只要您不忘记标签,就可以对当前产品版本进行热修复。
Keith Brings 2012年

@KeithBrings没错,我刚刚进行了测试,您确实可以从标签分支。
JoeGeeky 2012年

@MarjanVenema我不太关心系统上的负载,因为大量分支可能引起混乱。我也有点担心,在发布分支堆栈中所做的更改不会合并到应该获取它们的其他发布分支中,而不必担心主线。您遇到过这类问题吗?
JoeGeeky 2012年

@JoeGeeky:不,不要混淆。查看我的答案的更新。
Marjan Venema 2012年

2

这全都与上下文有关:您多久发布一次,以及一次发布中包含什么。

这是我使用B方法处理旧工作的一个案例研究(我们称其为故意分支)。

为了把故事放在上下文中,

  • 一个版本包含我们软件中的新功能:新游戏模式,新功能,新配置选项。
  • 发布周期相当长:我们的客户是大学,他们通常会坚持使用一项功能,通常为一年。

一直到主干进行主要开发,直到我们达到某个发行版的功能完善状态为止。到那时,我们将创建一个分支,例如projectname-january2012,并在该分支中进行质量测试和错误修复。一旦准备好公开发布,就可以在该分支中标记代码并发布。

但是,发行版的开发并没有到此结束。不可避免地,我们的客户发现了该发行版中的错误或小问题。因此,在这种情况下,我们要做的就是回到该分支,修补代码并创建要发布的january2012分支的新标记版本,然后将修补程序合并回主干。

在我们的案例中,这种方法是有利的,因为某些用户倾向于保留功能有限的旧版本,或者仅仅是因为在其基础架构上部署全新版本而不是修补程序的成本引起了一些问题。

因此,您必须问自己的问题是:

  • 我多久发布一次?
  • 我的发行版是否会100%向后兼容?
  • 我的客户可以完全升级来修复错误吗?

如果您经常发布,那么为每个分支都拥有分支可能不值得。但是,如果您的发布周期像我的旧用例一样长,并且部署,向后兼容性和客户端坚持旧版本可能会带来风险,那么选项B无疑将为您省去很多麻烦,并使事情变得更容易支持您的客户以最小的成本处理分支机构的混乱情况。


我喜欢您所说的那个选项。在这种情况下,我们是我们自己的客户(某种程度上来说),因此部署将在很大程度上由我们控制。我们也是Scrum商店,并且期望发布周期相当频繁(例如,每2-4周一次)。虽然我们希望支持滚动升级,但是向后兼容仅是实施升级所需的时间,所以……可能要花几分钟。从那声音中;根据您的经验;选项B 对我而言可能不是最佳选择。感谢您提供的信息,非常有趣。
JoeGeeky 2012年

是的,在这种情况下,选项B听起来很混乱,几乎没有回报。我只是想强调,这两种选择都是可行的,并且各有优势。我忘了明确提及:您如何处理错误修正?它们是专门放在新版本中还是在补丁/已修补旧版本中?
Bushibytes 2012年

1

我更喜欢选项A。在主干和分支发行版稳定后进行开发。这极大地限制了集成应用于生产版本的热修复程序的工作。

我已经签约帮助一个尝试了选项B的团队重回正轨。

需要考虑的几件事。

  • 通过所有活动的代码分支向前迁移修补程序。这可以通过合并,修补和/或重新开发来完成。应该全面管理这些内容,以确保将修补程序应用于所有适当的发行版,然后应用于主干。
  • 考虑功能分支,以使开发功能与主代码流隔离。建议将其用于实验更改。如果功能无法正常使用,请随意放弃功能分支。
  • 标记并跟踪您的合并点。
  • 在需要时分支发布。我发现这通常是在发布准备好发布候选版本时。在某些情况下,对主干引入不兼容的更改可能会强制和早期分支。考虑一个功能分支。

0

我已经在一个系统上工作了多年,该系统在您描述的两种方案之间使用了某种方式。关键是正在使用一种多级编号方案。外部级别基本上是API版本,它在分支上进行管理(当需要在多个分支上固定某些东西时可以进行适当的交叉合并),而内部级别则是完成的确切发布,并通过标签进行管理。

特别是,如果我们知道客户拥有的确切版本,我们就会确切地知道代码是从哪个源构建的,并且可以精确地重复,以便我们可以准确地了解发生了什么。这对于支持非常重要!但是分支的外部级别(我们当前发布的API版本)会随着时间的推移而发展(开发的主要干线获得了大多数新功能)。另外,当我们开发API的新主要版本时,我们将创建一个新分支来支持该API(因此主干始终可以是面向核心开发的),并考虑是否应该终止当前最旧的支持科。

因此,我建议将AB混合使用;两者都有良好的方面,但它们本身都不是完整的。利用两全其美。


0

过去,我已经使用TFS有效地实现了选项(B)。

分支/合并是一小段的很好的工具。困难不在于建立分支(这很愚蠢),也不在于将一周的工作量花在树上(通常也很容易)……这是将CI系统置于源代码管理之后才能自动工作您。

因为如果系统没有自动为您的分支构建和运行测试,那么分支就没有意义了。

我们已经定制了TFS的默认构建工作流程来识别变更集的相对路径,并建立了一个约定,定制可以通过该约定来识别新分支(而不是仅在某个开发根目录下的新子文件夹)。它运行平稳,易于分支,易于杀死分支,并且我们不断从系统中获得有关编译和测试的反馈。

我看到很多人宣称这些策略在TFS下是不可能的,并且我认为这是由于对基于XAML的构建引擎的可能性缺乏了解。TFS不仅是源代码管理,它是一个完整的解决方案,应按原样使用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.