当您想要进行持续集成时,最好使用的分支策略是什么?
- 发布分支:在主干上开发,为每个版本保留一个分支。
- 功能分支:在单独的分支中开发每个功能,只有在稳定后才合并。
一起使用这两种策略有意义吗? 例如,您为每个版本进行分支,但也为大型功能进行分支? 这些策略之一是否与持续集成更好地结合? 当使用不稳定的主干时,使用持续集成是否有意义?
What is the best branching strategy to use when you want to do continuous integration?
- Release Branching: develop on trunk, keep a branch for each release.
- Feature Branching: develop each feature in a separate branch, only merge once stable.
Does it make sense to use both of these strategies together? As in, you branch for each release but you also branch for large features? Does one of these strategies mesh better with continuous integration? Would using continuous integration even make sense when using an unstable trunk?
发布评论
评论(12)
如果您需要维护应用程序的多个版本,发布分支非常有用,甚至是绝对必需的。
功能分支也非常方便,特别是如果一个开发人员需要进行巨大的更改,而其他人仍然发布新版本。
所以对我来说,使用这两种机制是一个非常好的策略。
来自SVN 之书的有趣链接。
Release branches are very useful, and even absolutely required, if you need to maintain several versions of your app.
Feature branches also are very convenient, notably if one developer needs to work on a huge change, while others still release new versions.
So to me using both mechanisms is a very good strategy.
Interesting link from the Book of SVN.
我最近在使用 git 时开始喜欢这个模型。 尽管您的问题被标记为“svn”,但您仍然可以使用它。
持续集成在某种程度上可以发生在这个模型中的“开发”分支(或者无论你怎么称呼它)中,尽管为未来的版本提供长期运行的功能分支不会使它变得如此严格,以至于需要考虑代码中发生的每一个更改。 问题仍然是,你是否真的想要那样。 马丁·福勒做到了。
I've recently come to like this model when using git. Although your question is tagged "svn", you might still be able to make some use of it.
Continuous Integration can to some extent happen in the "develop" branch (or whatever you call it) in this model, though having long running feature branches for future releases wouldn't make it so rigid as to consider every change happening to code somewhere. The question remains, whether you'd really want that. Martin Fowler does.
持续集成不应该成为决定分支策略的任何因素。 您的分支方法应根据您的团队、正在开发的系统以及您可用的工具来选择。
话虽如此……
没有 这个问题在您获取图表的页面上的第四个问题中得到了回答: http://blogs.collab.net/subversion/2007/11/branching-strat/
Continuous integration should not be any kind of a factor in determining your branching strategy. Your branching approach should be selected based on your team, the system under development and the tools available to you.
Having said that ...
All of this was answered in the fourth question on the page that you took the diagrams from: http://blogs.collab.net/subversion/2007/11/branching-strat/
只要理解原理,就总能重新发明最佳实践。 如果您不理解原则,那么最佳实践将带您走这么远,然后由于一些相互冲突的外部要求而崩溃。
有关主线模型的最佳介绍,请阅读以下内容:https://web.archive.org/web/20120304070315/http://oreilly.com/catalog/practicalperforce/chapter/ch07.pdf
阅读链接。 一旦掌握了基础知识,请阅读以下由受人尊敬的 Henrik Kniberg 撰写的文章。 它将帮助您将主线模型与持续集成联系起来。
http://www.infoq.com/articles/agile-version-control
As long as you understand principles, you can always re-invent the best practices. If you don't understand principles, the best practices will take you that far before falling apart due to some conflicting external requirement.
For best intro into the Mainline Model, read this: https://web.archive.org/web/20120304070315/http://oreilly.com/catalog/practicalperforce/chapter/ch07.pdf
Read the link. Once you got the basics, read the following article by venerable Henrik Kniberg. It will help you relate Mainline Model with continuous integration.
http://www.infoq.com/articles/agile-version-control
Dave Farley,持续交付,参考基于主干的开发 (TBD) a> 作为持续集成(CI)和持续交付(CD)的基石。 他说:
他还说,
基于主干的开发 (TBD) 是至少将代码更改集成到主干(又名主干、主线)的实践每天一次 - 最好每天多次。 持续集成 (CI) 是一种类似的实践,只不过它还涉及使用自动化测试来验证代码更改。 最好的分支策略是直接在主干上工作,并通过结对编程来执行代码审查。 如果由于某种原因您无法配对,或者您只是真的想分支,请确保您的分支是短暂的(少于一天)。
对于大型功能(即需要超过一天的功能),请尝试将它们分解为小逻辑块,这些逻辑块可以集成到主干中而不破坏软件。 您还可以使用诸如 功能标记 和 按抽象分支,允许您部署不完整的工作而不影响最终用户。
Dave Farley, an author of Continuous Delivery, referred to Trunk Based Development (TBD) as the cornerstone of Continuous Integration (CI) and Continuous Delivery (CD). He says:
He also says,
Trunk Based Development (TBD) is the practice of integrating code changes into the trunk (a.k.a, master, mainline) at least once per day - preferably multiple times per day. Continuous Integration (CI) is a similar practice except that it also involves verifying the code changes using automated tests. The best branching strategy for this is to work directly off the trunk and to perform code reviews through Pair-Programming. If for some reason you can't pair, or you just really want to branch, make sure your branches are short-lived (less than a day).
For large features (i.e. ones that take longer than a day), try to break them into small chunks of logic which can be integrated into the trunk without breaking the software. You can also use techniques such as feature-flagging and branching by abstraction which allow you to deploy incomplete work without affecting end users.
当我们组建团队时,我们从最初开发我们即将负责的系统的供应商那里继承了基于版本的策略。 它一直有效,直到我们的客户要求几个开发的功能不应包含在版本中(仅供参考,约 25 万行代码,约 2500 个文件,带有 XP SDLC 的 Scrum)。
然后我们开始研究基于特征的分支。 这也工作了一段时间——大约两个月,直到我们意识到我们的回归测试过程将需要两周多的时间,再加上将发布的内容的不确定性,造成了巨大的不便。
当我们决定应该有 1. 稳定的主干和 2. 生产应该包含 ST、UAT 和回归测试的二进制文件(不仅仅是源 - 想想 CC)时,纯 SC 策略的最后一个“棺材上的钉子”就出现了。
这引导我们设计一种混合基于功能和基于版本的 SC 策略的策略。
所以我们有一个行李箱。 每个冲刺我们都会分支出冲刺分支(对于非敏捷人员来说,冲刺只是一个有时间限制的开发工作,具有基于复杂性的可变输出。)从冲刺分支我们创建功能分支并在其中开始并行开发。 一旦功能完成并经过系统测试,并且我们收到部署它们的意图,它们就会合并到冲刺分支 - 有些可能会跨多个冲刺,通常是更复杂的冲刺。 一旦冲刺接近结束并且功能完成......我们将冲刺分支“重命名”为“回归”(这允许 CruiseControl 无需任何重新配置即可拾取它),然后在 cc 构建上开始回归/集成测试耳朵。 当这一切完成后,它就会投入生产。
简而言之,基于特征的分支用于开发、系统测试和UAT功能。 sprint 分支(实际上是发布分支)用于选择性地按需合并功能和集成测试。
现在向社区提出一个问题 - 由于开发发生在许多分支上以及 CruiseControl 的重新配置开销,我们显然在执行持续集成方面遇到了困难。 有人可以建议和建议吗?
When we started our team we inherited a release-based strategy from the vendor that originally developed the system we were about to get in charge of. It worked up until the time when our customers requested that several developed features should not be included in a release (f.y.i. ~250k lines of code, ~2500 files, Scrum with XP SDLC).
Then we started looking at feature-based branches. This also worked for a while - like 2 months until the point we realized that our regression testing process would take over 2 weeks which combined with the uncertainty of what would be released created a huge inconvenience.
The final "nail in the coffin" of pure SC strategies came when we decided that we should have 1. stable trunk and 2. Production should contain ST, UAT, and Regression tested BINARIES (not just source - think CC.)
This lead us to devise a strategy that is a hybrid between feature and release-based SC strategies.
So we have a trunk. Every sprint we branch out the sprint branch (for the non-agile folks - a sprint is just a time-boxed development effort with variable output based on complexity.) From the sprint branch we create the feature branches and parallel development starts in them. Once features are complete and system tested, and we receive intent to deploy them, they are merged to the sprint branch - some may float across several sprints, usually the more complex ones. Once the sprint is near its end and the features are complete ... we "rename" the sprint branch to "regression" (this allows CruiseControl to pick it up without any reconfiguration) and then regression/integration testing begins on the cc-built EAR. When that is all done, it goes in production.
In short, feature-based branches are used to develop, system test and UAT functionality. The sprint branch (really the release branch) is used to selectively merge features on-demand and integration-test.
Now here is a question to the community - we are obviously having trouble performing continuous integration because of the fact that development happens on many branches and the reconfiguration overhead of CruiseControl. Can someone suggest and advice?
在我看来,你希望拥有一组有限的分支来集中精力。 由于您需要测试、代码质量指标以及许多有趣的东西来与构建一起运行,因此过多的报告可能会让您错过信息。
何时进行分支以及分支的内容通常取决于团队的规模和正在开发的功能的规模。 我不认为有黄金法则。 确保您使用的策略可以尽早/经常获得反馈,其中包括从功能一开始就涉及质量。 质量位意味着,当您随着团队的发展而实现自动化时,如果您为团队正在构建的大型功能集进行分支,那么您也必须让质量参与到团队中。
ps 您从哪里获得这些方法参考? - 不认为这些图表代表了所有选项
更新1:扩展了为什么我说这不是黄金法则。 基本上,对于相对较小的团队,我发现最好使用混合方法。 如果功能分支很长,则会创建功能分支,并且团队的一部分将继续添加较小的功能。
The way I see it you want to have a limited set of branches where you can focus. Since you want tests, code quality metrics, and many interesting things to run with the builds, having too many reports will probably get you to miss info.
When and what to branch, usually depends on the size of the team and the size of the features being developed. I don't think there is a golden rule. Make sure you use an strategy where you can get feedback early/often, and that includes having quality involved from the very beginning of the features. The quality bit, means that as you are automating as the team develops, if you branch for a large feature set a team is building, you gotta have quality involved in the team as well.
ps Where did you get those approach references? - doesn't feel that those graphs represent all the options
Update 1: Expanding on why I said it isn't a golden rule. Basically for relatively small teams I have found it best using an approach that is a mix. Feature branches are created if it is something long and part of the team will continue adding smaller features.
我认为你使用的工具是一个重要因素。
I think the tools you use are a big factor here.
我发现这个话题非常有趣,因为我的日常工作严重依赖分支机构。
希望您觉得这些链接很有趣。
I find the topic really interesting since I heavily rely on branches on my daily job.
Hope you find the links interesting.
答案取决于团队的规模、源代码控制的质量以及正确合并复杂变更集的能力。 例如,在 CVS 或 SVN 等完整分支源代码控制中,合并可能很困难,您可能会更好地使用第一个模型,而如果使用更复杂的系统(如 IBM ClearCase)并且团队规模更大,您可能会更好地使用第二个模型模型或两者的组合。
我个人会分离功能分支模型,其中每个主要功能都在单独的分支上开发,每个开发人员完成的每个更改都有任务子分支。 随着功能稳定,它们会合并到主干,您可以保持相当稳定并始终通过所有回归测试。 当您接近发布周期结束并且所有功能分支合并时,您稳定并分支了一个发布系统分支,您只在该分支上进行稳定性错误修复和必要的向后移植,而主干用于开发下一个版本,您再次分支新的功能分支。 等等。
通过这种方式,主干始终包含最新的代码,但您可以设法保持其相当稳定,在重大更改和功能合并上创建稳定的标签(标签),功能分支通过持续集成进行快速开发,并且可以经常使用单个任务子分支从功能分支刷新,使每个人在同一功能上工作保持同步,同时不影响其他团队在不同功能上工作。
同时,您拥有历史记录中的一组发布分支,您可以在其中为出于某种原因仍使用产品的先前版本甚至只是最新发布版本的客户提供向后移植、支持和错误修复。 与主干一样,您无需在发布分支上设置持续集成,它们会在通过所有回归测试和其他发布质量控制后仔细集成。
如果由于某种原因两个功能相互依赖并且需要彼此进行更改,您可以考虑在同一个功能分支上开发这两个功能,或者要求这些功能定期将代码的稳定部分合并到主干,然后刷新来自trunk 在干线分支之间交换代码。 或者,如果您需要将这两个功能与其他功能隔离,则可以创建一个公共分支,您可以在该公共分支上分支这些功能分支,并可以使用它在功能之间交换代码。
上述模型对于 50 名开发人员以下的团队和没有稀疏分支以及没有适当的合并功能(如 CVS 或 SVN)的源代码控制系统来说没有多大意义,这只会使整个模型的设置、管理和集成成为一场噩梦。
The answer depends on the size of your team and quality of your source control and the ability to merge correctly complex change sets. For example in full branch source control like CVS or SVN merging can be difficult and you might be better off with the first model, while if using more complex system like IBM ClearCase and with a larger size of team you could be better of with the second model or a combination of the two.
I personally would separate the feature branch model, where each major feature is developed on a separate branch, with task sub-branches for each change done by individual developer. As features stabilize they get merged to trunk, which you keep reasonably stable and passing all regression tests at all times. As you near the end of your release cycle and all feature branches merge, you stabilize and branch of a release system branch on which you only do stability bug fixes and necessary backports, while the trunk is used for development of the next release and you again branch off for new feature branches. And so on.
This way trunk contains always the latest code, but you manage to keep it reasonably stable, creating stable labels (tags) on major changes and feature merges, the feature branches are fast paced development with continuous integration and individual task sub-branches can be often refreshed from the feature branch to keep everyone working on the same feature in sync, while simultaneously not affecting other teams working on different features.
At the same time you have through the history a set of release branches, where you can provide backports, support and bugfixes for your customers who for whatever reason stay on previous versions of your product or even just latest released version. As with the trunk, you do not setup continuous integration on the release branches, they are carefully integrated upon passing all regression tests and other release quality control.
If for some reason two features are co-dependent and need changes done by each other, you can consider to either develop both on the same feature branch or to require the features to regularly merge stable parts of the code to trunk and then refresh changes from trunk to exchange code between trunk branches. Or if you need to isolate those two features from others, you can create a common branch off which you branch those feature branches and which you can use to exchange code between the features.
The above model does not make much sense with teams under 50 developers and source control system without sparse branches and proper merging capability like CVS or SVN, which would just make this whole model a nightmare to setup, manage and integrate.
我个人认为拥有稳定的主干并进行功能分支会更干净。 这样,测试人员等就可以停留在单个“版本”上,并从主干更新以测试代码完整的任何功能。
此外,如果多个开发人员正在开发不同的功能,他们都可以拥有自己单独的分支,然后在完成后合并到主干并发送要测试的功能,而测试人员不必切换到多个分支来测试不同的功能。
作为额外的好处,一定程度的集成测试是自动进行的。
I personally find it much cleaner to have a stable trunk and do feature branching. That way, testers and the like get to stay on a single "version" and update from trunk to test any feature that is code complete.
Also if multiple developers are working on different features, they can all have their own separate branches, then merge to trunk when they're done and send a feature to be tested without the tester having to switch to multiple branches to test different features.
As an added bonus, there is some level of integration testing that comes automatically.
我认为这两种策略都可以用于持续开发,只要您记住每个开发人员每天向主干/主线承诺的关键原则之一。
http://martinfowler.com/articles/continuousIntegration.html#EveryoneCommitsToTheMainlineEveryDay
编辑
我已经一直在阅读关于 CI 的这本书,作者建议通过发布是他们首选的分支策略。 我必须同意。 使用 CI 时,按功能进行分支对我来说毫无意义。
我将尝试解释为什么我会这样想。 假设三个开发人员各自使用一个分支来开发一个功能。 每个功能都需要几天或几周的时间才能完成。 为了确保团队持续集成,他们必须每天至少向主分支提交一次。 一旦他们开始这样做,他们就失去了创建功能分支的好处。 他们的更改不再与所有其他开发人员的更改分开。 既然如此,为什么还要费心去创建功能分支呢?
使用按发布分支需要更少的分支之间的合并(总是一件好事),确保所有更改尽快集成,并且(如果正确完成)确保您的代码库始终准备好发布。 按版本分支的缺点是您必须对更改更加小心。 例如,大型重构必须逐步完成,如果您已经集成了在下一个版本中不需要的新功能,那么必须使用某种 功能切换机制。
另一种编辑
关于这个主题有不止一种意见。 这是一篇博客文章,它是 CI 的专业功能分支
http://jamesmckay.net/2011/07/why-does-martin-fowler-not-understand-feature-branches/
I think either strategy can be used with continuous development provided you remember one of the key principles that each developer commits to trunk/mainline every day.
http://martinfowler.com/articles/continuousIntegration.html#EveryoneCommitsToTheMainlineEveryDay
EDIT
I've been doing some reading of this book on CI and the authors make suggest that branching by release is their preferred branching strategy. I have to agree. Branching by feature makes no sense to me when using CI.
I'll try and explain why I'm thinking this way. Say three developers each take a branch to work on a feature. Each feature will take several days or weeks to finish. To ensure the team is continuously integrating they must commit to the main branch at least once a day. As soon as they start doing this they lose the benefit of creating a feature branch. Their changes are no longer separate from all the other developer's changes. That being the case, why bother to create feature branches in the first place?
Using branching by release requires much less merging between branches (always a good thing), ensures that all changes get integrated ASAP and (if done correctly) ensures your code base in always ready to release. The down side to branching by release is that you have to be considerably more careful with changes. E.g. Large refactoring must be done incrementally and if you've already integrated a new feature which you don't want in the next release then it must be hidden using some kind of feature toggling mechanism.
ANOTHER EDIT
There is more than one opinion on this subject. Here is a blog post which is pro feature branching with CI
http://jamesmckay.net/2011/07/why-does-martin-fowler-not-understand-feature-branches/