假设您正在开发具有定期发布的软件产品。关于分支和合并的最佳实践是什么?将定期发布的分支切分给公众(或您的客户是谁),然后在主干上继续开发,或者将主干视为稳定版本,定期将其标记为发布,并在分支中进行实验工作。人们认为行李箱被认为是“黄金”还是被认为是“沙盒”?
20 回答
我已经在大型商业应用程序中尝试了这两种方法。
哪种方法更好的答案在很大程度上取决于您的具体情况,但我会写下我迄今为止的整体经验。
总体上更好的方法(根据我的经验):主干应该始终保持稳定。
以下是此方法的一些指导原则和好处:
- 在其自己的分支中对每个任务(或相关的任务集)进行编码,然后您将可以灵活地选择何时合并这些任务并执行发布。
- 在合并到主干之前,应该对每个分支进行 QA。
- 通过对每个单独的分支进行 QA,您将更容易准确地了解导致错误的原因。
- 该解决方案适用于任意数量的开发人员。
- 此方法有效,因为分支在 SVN 中几乎是即时操作。
- 标记您执行的每个版本。
- 您可以开发暂时不打算发布的功能,并准确决定何时合并它们。
- 对于您所做的所有工作,您都可以从提交代码中受益。如果你只在主干之外工作,你可能会经常保持你的代码未提交,因此不受保护并且没有自动历史记录。
如果您尝试做相反的事情并在主干中进行所有开发,您将遇到以下问题:
- 日常构建的持续构建问题
- 当开发人员为项目中的所有其他人提交问题时,生产力损失
- 更长的发布周期,因为你需要最终得到一个稳定的版本
- 不太稳定的版本
如果您尝试保持分支稳定并将主干作为开发沙箱,您将根本无法获得所需的灵活性。原因是您无法从主干中挑选要放入该稳定版本的内容。它已经在后备箱中混合在一起了。
我会说在主干中进行所有开发的一种特别情况是,当您开始一个新项目时。根据您的情况,可能还有其他情况。
顺便说一句,分布式版本控制系统提供了更多的灵活性,我强烈建议切换到 hg 或 git。
我已经使用过这两种技术,我会说在主干上开发并将稳定点作为版本分支是最好的方法。
上面那些反对说您将拥有的人:
- 日常构建的持续构建问题
- 当开发人员为项目中的所有其他人提交问题时,生产力损失
可能没有使用持续集成技术。
确实,如果您在白天不执行几次测试构建,比如每小时一次左右,就会让自己对这些问题持开放态度,这将很快扼杀开发的步伐。
白天进行几次测试构建会快速折叠主代码库的更新,以便其他人可以使用它,并且如果有人破坏了构建,也会在白天提醒您,以便他们可以在回家之前修复它。
正如所指出的,只有在运行回归测试的夜间构建失败时才发现构建损坏是完全愚蠢的,并且会很快减慢速度。
阅读 Martin Fowler 关于持续集成的论文。我们在大约 2,000 行 Posix sh 中为一个大型项目 (3,000kSLOC) 推出了自己的此类系统。
我倾向于采用“发布分支”的方法。树干是易变的。一旦发布时间临近,我会创建一个发布分支,我会更加谨慎地对待它。当这最终完成时,我会标记/标记存储库的状态,这样我就会知道“官方”发布的版本。
我知道还有其他方法可以做到这一点——这正是我过去所做的方式。
两个都。
主干用于大多数开发。但预计将尽最大努力确保行李箱的任何登记都不会破坏它。(部分由自动化构建和测试系统验证)
版本维护在它们自己的目录中,只对它们进行错误修复(然后合并到主干中)。
任何将使主干处于不稳定或非工作状态的新功能都在其自己的单独分支中完成,然后在完成时合并到主干中。
我喜欢并使用 Henrik Kniberg 在Version Control for Multiple Agile Teams中描述的方法。Henrik 在解释如何在具有多个团队的敏捷环境中处理版本控制方面做得很好(在传统环境中也适用于单个团队)并且解释他没有意义,所以我只发布“备忘单”(其中是自我解释)如下:
我喜欢它因为:
- 很简单:你可以从图片中得到它。
- 它工作(和扩展)很好,没有太多的合并和冲突问题。
- 您可以随时发布“工作软件”(本着敏捷精神)。
以防万一它不够明确:开发是在“工作分支”中完成的,主干用于 DONE(可发布)代码。检查多个敏捷团队的版本控制以获取所有详细信息。
关于保持主干稳定并在分支中完成所有工作的开发过程的一个很好的参考是 Divmod 的终极质量开发系统。快速总结:
- 所有完成的工作都必须有一张与之关联的票
- 为完成该工单的工作的每个工单创建一个新分支
- 来自该分支的更改不会在未经其他项目成员审核的情况下合并回主干线
他们为此使用 SVN,但这可以通过任何分布式版本控制系统轻松完成。
我认为你的第二种方法(例如,标记版本和在分支中做实验性的东西,考虑到主干稳定)是最好的方法。
应该清楚的是,分支在系统分支的时间点继承了系统的所有错误:如果将修复应用到主干,如果您将分支维护为一种发布周期终结者。如果您已经发布了 20 个版本,并且发现了一个可以追溯到第一个版本的错误,那么您将不得不重新应用您的修复 20 次。
分支应该是真正的沙箱,尽管主干也必须扮演这个角色:标签将指示代码在那个时间点是否“黄金”,适合发布。
这取决于你的情况。我们使用 Perforce,通常有几条开发线。主干被认为是“黄金”,所有开发都发生在分支上,当它们足够稳定可以集成时,它们会合并回主线。这允许拒绝不符合要求的功能,并且可以随着时间的推移提供独立的项目/功能可以获取的可靠增量功能。
合并和赶上主干中的新功能需要集成成本,但无论如何你都会遭受这种痛苦。让每个人都在主干上一起发展可能会导致狂野的西部局势,而分支可以让您扩展并选择您想要服用苦涩整合药丸的点。目前,我们在十几个项目中拥有超过一百名开发人员,每个项目都有多个版本,使用相同的核心组件,而且运行良好。
这样做的美妙之处在于您可以递归地执行此操作:一个大功能分支可以是它自己的主干,如果它,其他分支就会脱落。此外,最终版本会获得一个新分支,为您提供进行稳定维护的地方。
尝试根据新开发管理当前生产代码的维护充其量是有问题的。为了缓解这些问题,一旦测试工作完成并且代码准备好交付,代码应该分支到维护行。此外,主线应该分支以帮助稳定发布,包含实验性开发工作,或容纳生命周期跨越多个版本的任何开发工作。
仅当代码之间存在冲突的可能性(或确定性)而难以以任何其他方式管理时,才应创建非维护分支。如果分支机构不能解决后勤问题,它将创建一个。
正常发布开发发生在主线中。开发人员签入和签出主线以进行正常的发布工作。当前生产代码的补丁开发工作应该在该版本的分支中,然后在补丁通过测试并部署后与主线合并。非维护部门的工作应根据具体情况进行协调。
这取决于您的开发工作量。并行工作的多个团队将无法在同一代码(主干)上有效地工作。如果您只有一小部分人在工作,并且您主要关心的是削减一个分支,以便您可以继续工作,同时返回分支对当前有效的生产代码进行错误修复。这是对分支的微不足道的使用,并且不会太繁琐。
如果你有很多并行开发,你会希望每个工作都有分支,但这也需要更多的纪律:确保你的分支已经过测试并准备好合并回来。安排合并,因此两个组不会尝试同时合并等。
一些分支已经开发了很长时间,以至于您必须允许从主干合并到分支,以减少最终合并回主干时的意外数量。
如果您有一大群开发人员并了解适合您的情况,您将不得不进行试验。这是 Microsoft 的一个页面,可能有些用处:http: //msdn.microsoft.com/en-us/library/aa730834 (VS.80).aspx
我们将主干用于主要开发和分支用于发布维护工作。它工作得很好。但是分支应该只用于错误修复,没有重大更改,特别是在数据库方面,我们有一个规则,即只能在主干上发生架构更改,而不能在分支中发生。
如果你要完成一个发布周期、一个大特性,你就会被困在一个分支上。否则,我们在主干中工作,并在我们构建时为每个生产版本分支。
以前的生产版本在那个时候被移动到 old_production_ 并且当前的产品版本总是只是生产。我们的构建服务器所知道的关于生产的所有知识就是如何部署生产分支,并且我们通过强制触发器启动该构建。
我们遵循trunk=current 开发流,branch=release(s) 方法。在发布给客户时,我们将主干分支并保持主干向前滚动。您需要决定准备支持多少个版本。您支持的越多,您在错误修复上所做的合并就越多。我们尽量让我们的客户在后备箱后面不超过 2 个版本。(例如,Dev = 1.3,支持的版本 1.2 和 1.1)。
主干线一般是主要的开发线。
发布是分支的,通常在分支上完成实验或主要工作,然后在准备好与主开发线集成时合并回主干。
主干通常应该是您的主要开发源。否则,您将花费大量时间合并新功能。我已经看到它以另一种方式完成,它通常会导致很多最后一分钟的集成问题。
我们标记我们的发布,以便我们可以快速响应生产紧急情况,而无需分发积极的开发。
对我来说,这取决于我使用的软件。
在 CVS 下,我只会在“主干”中工作,从不标记/分支,因为否则真的很痛苦。
在 SVN 中,我会在主干中做我的“最前沿”的东西,但是当是时候进行服务器推送时,会得到适当的标记。
我最近切换到 git。现在我发现我从不在后备箱工作。相反,我使用了一个名为“new-featurename”的沙箱分支,然后合并到一个固定的“current-production”分支中。现在我想起来了,我真的应该在合并回“当前生产”之前创建“release-VERSIONNUMBER”分支,这样我就可以回到旧的稳定版本......
这实际上取决于您的组织/团队管理版本的能力以及您使用的 SCM。
- 如果下一步(在下一个版本中)可以轻松计划,那么最好在主干中进行开发。管理分支机构需要更多的时间和资源。但是如果下一个不能轻易计划(在更大的组织中一直发生),你可能最终会选择樱桃提交(数百/数千)而不是分支(几个或几十个)。
- 使用 Git 或 Mercurial,管理分支比 cvs 和 subversion 容易得多。我会选择稳定的主干/主题分支方法。这就是 git.git 团队使用的。阅读:http ://www.kernel.org/pub/software/scm/git/docs/gitworkflows.html
- 在 Subversion 中,我首先应用了在主干中开发的方法。在发布日期方面有相当多的工作,因为每次我都必须挑选提交(我的公司不擅长计划)。现在我是 Subversion 方面的专家,并且非常了解在 Subversion 中管理分支,所以我正在转向稳定的主干/主题分支方法。它比以前好得多。现在我正在尝试 git.git 团队的工作方式,尽管我们可能会坚持使用 Subversion。
这是我更喜欢的 SVN 设计:
- 根
- 发展
- 分支机构
- 特色1
- 特征2
- ...
- 树干
- 分支机构
- 测试版
- 标签
- 树干
- 释放
- 标签
- 树干
- 发展
除了需要自己的分支的主要功能外,所有工作都从开发/主干完成。在针对开发/主干测试工作后,我们将测试问题合并到测试/主干中。如有必要,将针对 beta 服务器测试代码。当我们准备好推出一些更改时,我们只需将适当的修订合并到发布/主干和部署中。
可以在 beta 分支或 release 分支中制作标签,这样我们就可以跟踪 beta 和 release 的特定版本。
这种设计提供了很大的灵活性。如果某些修订在 beta 中未通过测试,它还使我们可以轻松地将修订留在 beta/trunk 中,同时将其他修订合并到 release/trunk。
对于颠覆公约问题恕我直言,没有万能的答案。
这实际上取决于项目的动态和使用它的公司。在一个非常快节奏的环境中,当一个发布可能每隔几天就会发生一次,如果你尝试虔诚地标记和分支,你最终会得到一个无法管理的存储库。在这样的环境中,需要时分支的方法将创建一个更易于维护的环境。
另外-根据我的经验,从纯粹的管理角度来看,在您选择时在 svn 方法之间切换非常容易。
我知道效果最好的两种方法是按需分支和每个任务分支。当然,这些是完全相反的。就像我说的 - 这完全取决于项目动态。