问题 在开发/维护Web应用程序时,我应该使用哪种分支策略?


我正在尝试为Web应用程序项目确定最佳分支策略。以下是我到目前为止所提出的建议,我将非常感谢任何评论和经验。

我看到它的方式有两个主要的分支策略:“按版本分支”和“按功能分支”。

“发布分支”:发展在行李箱上进行。当发布时间临近时,将为该发行版创建一个分支。然后稳定/测试该分支,最后进行释放。在发布之后,分支将合并回主干,同时保持发布分支处于活动状态以进行错误修复。是否应用了错误修复,然后将其合并到主干中(如果主干上的开发没有以其他方式使错误重叠)。新功能将添加到主干,不会影响发布分支。 当新的发布时间临近时,将创建一个新的发布分支a.s.o.

“按功能划分”:主干始终是“生产”主干(现场代码)。错误修正直接提交到主干。下一版本的功能是在功能分支中开发的.Bugfixes会不时合并到功能分支中。当发布时间到来时,功能分支将合并到主干中,并且生命周期将继续。

现在,我认为这两种策略之间的实际区别在于“通过发布”允许您维护软件的不同生产版本(当客户A具有版本1和客户B版本1.5时,客户端是此处的付费客户案件)。相比之下,使用“按功能”策略,您只能支持当前的生产版本(所有客户端都使用最新版本)。

因为在一个典型的 Web应用程序 所有客户端都使用相同的“最新”版本(因为它们都访问相同的服务器),我认为“按功能”方法是最常用的。它消除了合并“跨层次结构”的需要,比如当必须将错误修复应用于所有3个版本时。

所以我现在的状态是我应该选择“逐个分支”。如果重要,我的团队不是很熟练。


997
2017-12-22 13:33


起源

感谢您提出这个问题 - 我真的很享受每个人的回复。 - Tom Anderson


答案:


如果您在任何时候只有一个版本,并且您在一个功能分支中进行所有开发,那么这些方法实际上是相同的。

如果你逐个功能意味着马上就有几个分支,我会像瘟疫一样避免它。更多的分支意味着更多的合并,这本身就是一种痛苦,而且更加融合地狱。连续集成到单个代码行要好得多。

如果您的部署过程比分支,测试,上线更复杂,那么逐个发布的优势在于您可以在不同的阶段同时拥有多个发布分支:一个是实时的,并且根据需要进行了修复,以及另一个正在稳定,测试,通过验收等,而继续在后备箱上继续发展。另一方面,如果你有一个实时主干,一旦你将一个功能分支合并到一个视图中来实现它,你就失去了对当前实时系统进行错误修正的能力。功能分支合并成为一个不归路。


5
2017-12-22 14:57



我之前没有想过这个,有趣的观点1+来自我:-) - Alex KeySmith
嗯..你提到“合并一个功能与 让它活着在这种情况下有一个问题,因为正如你所说,你刚刚失去了在实时系统上进行错误修正的能力。但对我来说,合并一个功能意味着:功能的合并和新版本的发布是一个问题。换句话说,新功能的合并意味着在合并之后,主干直接作为新版本发布。这也意味着客户端在合并之前已经测试并接受了新功能。但是现在我正在阅读评论它听起来有点怪异...... - BernardMarx
@BernardMarx:我认为你已经发现了问题:在合并之前你无法测试将要生效的代码,因为它在那之前就不存在了。但是一旦你合并,你就会承诺。我想有一个狭窄的窗口:你可以冻结主干,在开发机器上进行合并,运行预生产QA 没有登记入住,然后提交合并,如果它通过,直接承诺提交代码。如果您在此期间迫切需要修复live,您可以解冻主干,修复,然后重新启动功能合并。不要以为我想试试这个! - Tom Anderson
我听说,合并不是Git或Mercurial的痛苦。 - Dlongnecker
@Ziplin:更好的工具 - 比如Git和Mercurial - 削减了一些可简化的合并复杂性。但是仍然存在不可简化的复杂性 - 你的代码结束了 这里 知道如何处理信用卡和PayPal,但是你要合并的代码 那里 现在让客户用礼品卡付款。没有工具可以帮助你。合并越早越频繁,因为它可以让你处理分歧,而它仍然很小。 - Tom Anderson


你在开发什么样的软件?收缩包装?开源项目?如果是这样,那么请使用“按释放分支”或“不稳定主干”方法。特别是如果你的发布周期是每隔六个月到一年。

但是,如果你维持一个基于网络的项目,其变化频率较短,比如每隔几周或更短一次,那么请选择“逐个分支”或“稳定主干”方法。这种方法的问题在于集成多个功能更改,这些更改具有彻底的更改,使合并过程不那么有趣。这真的很难。

但这两种方法都运作良好,但如果你需要两者呢?也就是说,您有一个项目,每两周进行一次大型功能更改,但您发现有许多错误修复,您不能等待这些功能更改准备就绪。 Trunk是您的发布分支,具有“按功能分支”方法。如果你能获得两个版本并拥有自己的分支怎么办?

看看这个 博客文章 通过CollabNet的Bob Archer。他的敏捷发布策略可以为您提供最佳解决方案。我用过这个。它非常灵活。尽管Bob没有在他的图表中显示它,但您可以同时拥有多个发布分支。这意味着您可以拥有一个已准备好部署到生产阶段的发布分支,以及另一个正在准备进行最终QA检查的发布分支。但要考虑两件事:

首先,您的开发人员合并有多好?即使它是一个小团队,您也无法自己执行敏捷发布策略方法。每个人都必须尽自己的一份力,他们真的必须了解合并以及他们用来进行合并的工具。

其次,您需要很好地掌握准备好的变化和即将变化的变化。发布管理是使这项工作像时钟工作的关键。准备好后的每个功能都需要分配给发布分支并合并到它。

无论您选择哪种方法,都可以归结为您正在开发的内容以及您为该开发发布的更改频率。 


5
2017-12-22 15:12



这种“敏捷发布”策略(与敏捷开发的发布策略截然相反,但从不介意)看起来像是涉及令人瞩目的合并量。合并到发布分支的频率是多少?如果每隔几天,它就像一个不稳定的行李箱,但是随着时间的推移,行李箱的作用会在不同的分支之间传递。这应该有效,并且比稳定的行李箱更灵活。但是如果合并相距很远,我就是看不到这种情况 - 如果在两个或更多任务分支上进行大规模重构,那么你就会得到一个七圈合并地狱。 - Tom Anderson
@Tom Anderson:仅在功能完成时才会发布合并到发布分支。理想情况下,应该只有一个从功能分支到发布分支的合并。现在说,并非所有问题都是第一次在功能分支中解决。因此,如果在功能分支而不是发布分支中更好地解决,则可以从功能分支到发布分支进行后续合并以进行修补程序修复。 - jgifford25
@Tom Anderson:你是对的。如果发布版本的合并距离很远(超过几周),您可以减少合并开销,并通过发布或按功能分支方法分支。 - jgifford25
提升技能观点的方法。我编辑了原帖,说明技能有限 - BernardMarx


冒着让你更进一步困惑的风险:你可以拥有发布分支机构  在功能分支上进行所有更改。这些事情并不相互排斥。

话虽这么说,听起来你不需要并行发布系列,你想要经常部署,甚至可能 一直。因此,您可能希望拥有一个可以随时发布的“稳定主干”。功能分支有助于保持中继线稳定,因为只有在完成更改并且已经证明自己时才会合并回主干。

所以我会说你的选择很合适。


2
2017-12-22 15:11



持续部署的一种方法是在分支上开发功能,并且只有在它们准备好上线时才合并到主干。这使得功能的添加成为原子 - 它们不存在或完整 - 但意味着你有大量的,不常见的合并。另一个是连续集成,但以某种方式隐藏功能,直到它们准备好上线,使用某种配置开关,让您在内部环境中公开它们。这意味着更平滑的集成,但是有点混乱,并且使测试复杂化,因为您必须测试功能关闭和功能开启模式。 - Tom Anderson
虽然您可能希望将正在进行的功能设置为可选 - Google实验室的一种方法。也许。 - Tom Anderson
无论如何(并且抱歉发表三条评论),我得到的印象是,持续部署人员非常支持单一代码行与持续集成(这来自精益制造模型,这是该运动的智力起源),以及我认为他们的方法是需要逐步开发功能。不过,我绝不是任何精益专家,我喜欢阅读更多关于这个特定问题的内容。 - Tom Anderson
@Tom:您不必推迟整个合并 - 您可以定期将更改从主干到功能分支合并到您开发时保持同步,以便最终重新集成是微不足道的。当然,如果进入主干的变化很大,那么即使这些合并也会很痛苦。除了将重大变化分解为更小的可纠正变化之外,没有任何其他解决方案。 - Wim Coenen
没错,这有助于缩小合并。但是,如果在功能完成时仅将功能分支合并到主干中,则从主干到功能分支的更改必然是特征大小的。我想,这是否是痛苦取决于功能有多大。 - Tom Anderson


这些选择并不相互排斥 - 同时使用两者。


2
2017-12-22 15:10





我倾向于将Git用于我的项目,但我倾向于遵循的过程就像这样(并且也适用于Subversion):

  • 对于每个新功能,请为该功能创建分支。
  • 当一切正常时,将其合并到 staging 分支,并将其部署到登台服务器(你有其中一个,对吧?)
  • 一旦我们确定客户端对暂存时的内容感到满意,我们就会将暂存分支合并到生产分支中,将其标记为类似 production_release_22 要么 production_release_new_feature_x,然后将该标记部署到生产服务器。

标签是 决不曾经 更新 - 一旦部署了某些内容,它就会保持这种状态,直到构建,测试和标记更多更改 - 然后部署新标记。确保它是 标签 部署而不是 分支机构,我让自己(或其他人)不做“我只是提交一个快速更改并更新服务器而不进行测试”。

到目前为止,它对我来说非常好用。


1
2017-12-22 14:59



我真的不明白你的升级分支是什么。对我来说,它听起来像一个功能分支,其中后备箱已更改合并到其中。因此与与主干保持同步的功能分支基本相同。我可能在这里争论语义...... - BernardMarx
登台分支是完成所有事情(但不一定完全由客户端测试/确认)的地方 - 登台服务器从登台分支运行代码,但生产服务器只运行生产分支中的标签(当我们确认是时候部署更改时,staging会合并到其中。 - girasquid
如果您调用了临时分支“trunk”和生产分支“release”,这是否与其他人建议的逐个功能和发布策略基本相同?还是有微妙的差异? - Tom Anderson
基本上是一样的,是的 - 我会说唯一的主要区别是使用标签代替分支进行生产部署。 - girasquid