【问题标题】:Branch by feature - Advantages/disadvantages?按功能分支 - 优点/缺点?
【发布时间】:2025-11-23 10:40:01
【问题描述】:

我目前在一个项目中工作,分支和合并从一开始就没有很好地工作。为了改变这一点,我们一直在讨论很多不同的方法来做到这一点。我假设每个人都有自己的关于如何做这类事情的哲学,所以它似乎也在这里。

我们一直在谈论的一件事是按功能进行分支。对于这种特定方法的好坏,我们碰巧有非常不同的看法。

您以前有过这样做的经验吗?它运作良好吗?你有问题 - 什么样的问题?

我知道这个问题并没有真正的正确答案,但我发现听到世界各地其他开发人员的意见非常有趣,而 stackowerflow 似乎是一个很好的地方。

【问题讨论】:

标签: tfs branch branching-and-merging


【解决方案1】:

功能分支的替代方法是功能切换(即代码中的开关可以使功能可用或不可用)。它们在这方面非常有用。他们可以允许开发和部署新功能,但只有在切换...良好切换(甚至是一个词)时才可用。我想这有点像整个谷歌实验室的想法。

这里要注意的一点是,如果在开发过程中没有仔细考虑和测试,这些切换本身也可能会导致戏剧性的变化。实际上,您正在增加您需要执行的测试量,以查看启用和禁用功能的情况。如果您有多个功能正在开发中,那么您需要了解它们如何与启用/禁用状态的各种组合进行交互。

话虽如此,如果做得好,它们也会带来很大的好处。您可以向某些用户(高级用户或该功能的拥护者等)发布一项功能,而不会影响所有人。如果认为它引起了问题,则可以通过更改存在某些配置元素的 DB 记录来将其关闭。

一旦给定的功能被认为已通过集合,建议移除切换并将其作为整个应用程序的一部分。

话虽如此,我不认为功能分支不好,但它确实依赖于每个人都理解源代码控制和合并的概念,并确保分支不会与主分支过于脱节而导致一个大规模的 OMG 类型合并。

我最近参加了由 Thoughtworks 主办的一次会议,Martin Fowler 讨论了这个话题。演讲的重点是持续交付以及这如何帮助克服缓慢且有风险的部署。请参阅http://www.thoughtworks.com/events/thoughtworks-continuous-delivery-devops 或搜索持续交付以获取更多信息。

【讨论】:

  • 非常有趣。我确实看到了使用切换开关的观点。但是,考虑到我永远不想发布具有一个完整功能和一个不完整功能的东西(尽管由于切换而无法使用事件),我不会对使用它感到满意。如果目的是测试完成的功能,即使是为了测试,我也不想发布不完整的代码。你明白我的意思了吗?
  • 我愿意,而且我必须承认,我绝不是在练习持续交付,但我确实认为它有很多优点。特别是快速反馈循环的一些好处,克服了单一的怪物合并和缓慢而有风险的部署。就像我说的那样,对我来说,这意味着更完整的测试制度,以确保任何功能组合都不会导致问题。
【解决方案2】:

我们按功能使用分支,它对我们非常有效。最大的优势是特性团队知道他们正在做的事情不会影响其他特性团队,直到新特性被集成(在我们的例子中是 Main)。

当我们完成一个新功能(并且分支已合并到 Main)时,我们将分支移动到分支历史文件夹中。这使开发人员需要查看的分支(文件夹)数量保持在最低限度。

在我们的例子中,没有人在 Main 分支中工作。所有开发都在功能分支中完成。初始开发(在第一次发布到生产之前)在开发分支中完成。在第一次发布到生产环境后,所有开发都在一个新的功能分支中完成。

【讨论】:

  • Scott,你如何“将分支移动到分支历史文件夹”?您能否向我们展示您的文件夹结构示例?
  • Blaise,要创建一个分支历史文件夹,在与 Main 相同的级别创建一个名为 BranchHistory 的新文件夹。要将功能分支移动到 BranchHistory,请右键单击功能分支并选择移动。对话框将询问将分支移动到哪里,选择 BranchHistory。
  • 这听起来很简单。谢谢。
【解决方案3】:

如果您有一个中小型团队,那么当您并不真正需要完全的分支隔离时,请避免使用额外的分支……尤其是如果您的开发团队的文化反对正确地分支和合并。也许为了换取更少的分支来维护,确保所有被允许进行合并的开发人员虔诚地遵循合并实践。搁置集(在 TFS 中)和短期功能分支是一种很好的技术,可以最大限度地减少合并开销和相关风险。

详情

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

  1. 在同一个分支中工作: 开发松散耦合或不相关代码的开发人员可以相对安全地直接在同一个开发(或“集成”)分支中工作。错误修复和非破坏性更改非常适合这里(降低主要回归影响其他开发人员的风险)。持续集成构建和门控构建是降低许多开发人员在同一分支工作的风险的两个最佳实践。 切换注意:功能切换可用于进一步避免需要分支,但请确保测试/维护切换行为的开销不会比使用分支更具风险。

  2. 搁置集:使用您的版本控制系统的功能来保存特定于开发人员的原型分支中的未决更改。签入 TFS(Team Foundation Server)的开发人员可以使用搁置集而不是个人分支(或许多微功能/任务分支),如果他们是唯一需要在签入集成/开发分支之前开发和测试功能的人.我相信其他版本控制系统也有类似的结构 ANTIPATTERN: 本地工作区自动为每个开发人员提供临时隔离...但开发人员需要经常/每天在源代码控制中的某处检查他们的更改,以防止丢失数天以上仅限本地工作的风险.)

  3. 短期分支:当您确实需要一个分支进行隔离时(例如多个开发人员需要处理的破坏性功能),那么创建短期功能分支就是其中之一好方法。我推荐一个分支命名约定,使分支的使用随着时间的推移保持良好的定义和唯一性。

上述工作流程的主要优势在于,它最大限度地减少了合并税(前向/反向集成(向下/向上合并)所花费的时间),而不是开发直接提高客户满意度的功能。

示例场景:新的“Cool”功能将破坏现有功能并构建直到完成。它还需要 2 个以上的开发人员在相同的代码库上进行协作(消除使用 Shelveset 的选项)。 “Cool”的开发所有者创建名为 Cool1 的分支,然后开发和集成测试功能的第一个版本。开发所有者负责每天(最多每周一次)合并父级更改。 确认准备好合并(父合并做子(FI),所有 UT 和核心验收测试运行并仍然通过)。合并到父分支 (RI),然后确认父分支中的工作(所有 UT 和核心验收测试通过),然后删除 Cool1 功能分支(清理)。
合并到 dev/integration 分支后更彻底地测试 Cool 功能。 (测试资源有限,因此避免每个分支都使用完整的测试环境。)Cool 的错误修复和战术增强/重构将直接在 Dev 分支中完成(当分配的开发人员需要很多天才能在签入前进行本地化开发/测试时,使用搁置集)。如果稍后需要对 Cool 进行重大(多开发)返工,则创建一个新的 Cool2 分支。

TFS2010 移动/重命名注意: TFS 2010 移动和重命名行为已更改(从 TFS 2008 开始)以进行移动和重命名 =“分支到新名称/位置,然后将原始项目标记为已删除”。这意味着如果您不想在源代码管理 \Dev\ 中看到它们,您应该只删除不活动的功能分支,而不是将分支移动到不同的文件夹。这也意味着启用查看已删除文件夹的开发人员将始终将这些已删除(或移动或重命名)的短期分支视为可能会变得混乱的“幽灵”。 (这就是您可以查看历史记录或取消删除已删除项目的方式。)

【讨论】:

    【解决方案4】:

    使用自己的分支处理合并目标的团队越多,处理冲突所需的沟通就越好。

    警惕代码中的高流失率、耦合性和公共区域。这些将是争论的领域。

    在 TFS 中可以有效地按功能进行分支,但与 dev 中的任何事情一样,越复杂,产生的开销就越多。

    【讨论】:

      【解决方案5】:

      Git 比 TFS 好得多。我已经使用 git 超过 7 年了,在此之前使用过 TFS。最近我换了工作,我必须使用 TFS。仅仅拥有一个 dev 分支并且所有开发人员都在同一个 dev 上工作并不能提供任何适当的审查机会。我喜欢 git 代码审查是一个正式的过程这一事实。

      使用 git,我通过创建与功能/工作项相关的分支来处理本地分支。完成工作后,您可以将其推送到远程分支。然后,您将从远程分支向您的开发/集成分支发出拉取请求。一旦拉取请求被审查,审查者会将 PR 合并到 dev 分支。这对我来说非常有效。

      【讨论】: