按功能分支 - 优缺点?

26

我目前在一个项目中工作,从一开始分支和合并就一直表现不佳。为了改变这种情况,我们已经讨论了很多不同的方法。我认为每个人都有自己关于如何做这种事情的哲学,这里似乎也是如此。

我们讨论过的一件事是按功能进行分支。我们恰好对这种特定方法的优点和缺点持有非常不同的观点。

你有这方面的经验吗?是否有效?你遇到了问题 - 是什么问题?

我知道这个问题不会有一个正确的答案,但我很有兴趣听听世界各地其他开发人员的意见,而stackoverflow似乎是一个很好的地方。


2
我知道这个帖子有点老了,但今天我刚注意到ThoughtWorks的Martin Fowler有一个关于特性分支及其替代方案的视频。请查看 - http://www.thoughtworks.com/perspectives/30-06-2011-continuous-delivery - Mr Moose
谢谢!总是很好看看并看看是否可以获得更多反馈! :) - MrW
5个回答

17
我们使用按特性分支的方式,这对我们非常有效。最大的优点是特性团队知道他们正在工作的内容不会影响到其他特性团队,直到新特性被集成(在我们的情况下是集成到主分支)。
当我们完成一个新特性(并且该分支已经合并到主分支中),我们将该分支移到“分支历史”文件夹中。这样可以将开发人员需要查看的分支(文件夹)数量保持在最小限度。
在我们的情况下,没有人在主分支上工作。所有开发都在特性分支上进行。在第一次发布到生产环境之前的初始开发,是在开发分支上进行的。在第一次发布到生产环境后,所有开发都在新的特性分支上进行。

Scott,你如何将“分支移动到分支历史文件夹”?你能展示一下你的文件夹结构的例子吗? - Blaise
1
Blaise,要创建一个分支历史文件夹,请在与Main同级别的位置创建一个名为BranchHistory的新文件夹。要将特性分支移动到BranchHistory,请右键单击特性分支并选择Move。对话框会询问要将分支移动到哪里,请选择BranchHistory。 - Scott Bruns
听起来相当容易。谢谢。 - Blaise

11
如果你有一个小到中等规模的团队,当你不需要完全隔离的分支时,请避免额外创建分支...特别是如果你的开发团队文化反对正确分支和合并。也许为了减少需要维护的分支,确保所有被允许进行合并的开发人员都要严格遵循合并实践。Shelvesets(在TFS中)和短期功能分支是减少合并开销和相关风险的好技术。

详情

这里是我发现的一种平衡生产力和版本控制安全性的模式(适用于大约25个开发人员和3个测试人员的团队):

  1. 在同一分支上工作: 开发人员可以相对安全地在同一Dev(或“集成”)分支上直接工作,前提是他们的代码是松散耦合或无关的。修复bug和非破坏性更改很好地适合在这里(较低的风险会影响其他开发人员)。持续集成构建和门禁构建是缓解多个开发人员在同一分支上工作的风险的两个最佳实践。 提示:功能切换可以用来进一步避免需要创建分支,但是确保测试/维护切换行为的开销不会比使用分支更加危险。

  2. Shelvesets: 使用版本控制系统的功能将待处理的更改保存在特定于每个开发人员的原型分支中。如果只有一个人需要在集成/Dev分支之前开发和测试该功能,那么在TFS(Team Foundation Server)中签入的开发人员可以使用shelvesets而不是个人分支(或许多微型功能/任务分支)。我相信其他版本控制系统也有类似的构造。 反模式:本地工作区自动为每个开发人员提供临时隔离...但是开发人员需要经常/每天在源代码控制中的某个位置签入他们的更改,以防止丢失几天或更长时间的本地工作。

  3. 短期分支: 当你确实需要一个用于隔离的分支(例如用于多个开发人员需要开发的破坏性功能)时,创建短期功能分支是一种不错的方式。我建议使用分支命名约定,以使分支使用在一段时间内得到很好的定义和唯一性。

以上工作流的主要优势在于最小化合并税(花费时间将前/后向集成(向下/向上合并)),而不是开发直接改善客户满意度的功能。

示例场景: 新的“酷炫”功能会破坏现有的功能和构建,直到完成为止。它还需要2个以上的开发人员在同一代码库上进行协作(消除使用Shelveset的选项)。"酷炫"的开发所有者创建名为Cool1的分支,然后开发和集成测试功能的第一个版本。开发所有者每天(绝对最多每周一次)负责合并父级更改。确认准备好合并(父级合并子级(FI),运行所有UT和核心验收测试仍然通过)。合并到父级(RI),然后确认在父分支中运行正常(所有UT和核心验收测试都通过),然后删除Cool1功能分支(清理)。
在将Cool功能合并到开发/集成分支后更全面地测试该功能。(由于测试资源有限,请避免为每个分支使用完整的测试环境。)如果需要修复漏洞和战术性增强/重构Cool,则直接在Dev分支中完成(当分配的开发人员需要很多天本地开发/测试才能提交时使用Shelveset)。如果以后需要对Cool进行大型(多开发人员)重构,则创建一个新的Cool2分支。

TFS2010移动/重命名说明: TFS 2010移动和重命名行为已更改(从TFS 2008),以使移动和重命名=“将分支移至新名称/位置,然后将原始项标记为已删除”。这意味着,如果您不想在源代码控制\Dev\中看到这些非活动功能分支,只需删除它们即可,而不是将分支移动到其他文件夹中。这也意味着启用查看已删除文件夹的开发人员将始终将这些已删除(或已移动或已重命名)短暂分支视为“幽灵”,这可能会导致混乱。(这是如何查看历史记录或取消删除已删除项的方法。)


4
一个替代分支的功能是特性切换(即代码中可以使特定功能可用或不可用的开关)。在这方面,它们非常有用。它们可以允许新功能的开发和部署,但只有在切换被切换后才可用(这是一个词吗?)。我想象这有点像整个Google实验室的想法。
需要注意的是,如果在开发过程中没有仔细考虑和测试这些切换,它们本身也可能引起问题。事实上,您需要增加测试的数量,以查看启用和禁用功能时的行为如何。如果您正在开发多个功能,则需要查看它们与启用/禁用状态的各种组合之间的相互作用。
话虽如此,如果做得好,它们也会带来巨大的好处。您可以将某个功能发布给某些用户(高级用户或该功能的支持者等),而不会影响所有人。如果发现它会造成问题,可以通过更改DB记录或某些配置元素的存在来关闭它。
一旦确定某个特定功能已经通过了检验,建议删除切换并将其纳入整个应用程序。

话虽如此,我并不认为特性分支是不好的,但它确实依赖于每个人都理解源代码控制和合并的概念,并确保分支与主分支不会相差太远,导致一次大规模的合并。

我最近参加了Thoughtworks举办的一次会议,Martin Fowler在会上讨论了这个问题。讲座的重点是持续交付以及如何帮助克服缓慢和风险高的部署。请查看http://www.thoughtworks.com/events/thoughtworks-continuous-delivery-devops或搜索“连续交付”以获取更多信息。


非常有趣。我确实理解你使用切换的观点。然而,考虑到我从不想发布一个完整功能和一个不完整功能的产品(即使由于切换原因不可用),我不太愿意使用它。如果目的是测试已完成的功能,即使是为了测试,我也不想发布不完整的代码。你明白我的意思吗? - MrW
我必须承认,我并没有实践持续交付,但我认为它有很多优点。特别是快速反馈环路、克服单一大合并和缓慢、高风险的部署等方面的好处。不过,对我来说,它意味着更完整的测试体制,以确保任何功能组合都不会引起问题。 - Mr Moose

0

如果有更多的团队在他们自己的分支上工作,以合并目标为中心,你需要更好的沟通来处理冲突。

要注意代码中高频率变动、耦合和常见区域。这些将是争议的焦点。

按特性分支可以在TFS中有效地完成,但是像开发中的任何事情一样,你越复杂,就会产生越多的开销。


0

Git比TFS好得多。我已经使用git超过7年了,之前用过TFS。最近我换了一份工作,必须使用TFS。只有一个开发分支并且所有开发人员都在同一个开发分支上工作,并不允许进行适当的代码审查。我喜欢在git中代码审查是一个正式的过程。

使用git,我通过创建与特性/工作项相关的本地分支来工作。完成工作后,您可以将其推送到远程分支。然后,从远程分支发起拉取请求到您的dev / integration分支。一旦拉取请求得到审查,评审人员将合并PR到dev分支。这对我非常有效。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接