我目前在一个项目中工作,分支和合并从一开始就没有很好地工作。为了改变这一点,我们一直在讨论很多不同的方法来做到这一点。我假设每个人都有自己的关于如何做这类事情的哲学,所以它似乎也在这里。
我们一直在谈论的一件事是按功能进行分支。对于这种特定方法的好坏,我们碰巧有非常不同的看法。
你以前有过这样做的经验吗?它运作良好吗?你有问题 - 什么样的问题?
我知道这个问题并没有真正的正确答案,但我发现听到世界各地其他开发人员的意见非常有趣,而 stackowerflow 似乎是一个很好的地方。
我目前在一个项目中工作,分支和合并从一开始就没有很好地工作。为了改变这一点,我们一直在讨论很多不同的方法来做到这一点。我假设每个人都有自己的关于如何做这类事情的哲学,所以它似乎也在这里。
我们一直在谈论的一件事是按功能进行分支。对于这种特定方法的好坏,我们碰巧有非常不同的看法。
你以前有过这样做的经验吗?它运作良好吗?你有问题 - 什么样的问题?
我知道这个问题并没有真正的正确答案,但我发现听到世界各地其他开发人员的意见非常有趣,而 stackowerflow 似乎是一个很好的地方。
我们按功能使用分支,它对我们非常有效。最大的优势是特性团队知道他们正在做的事情不会影响其他特性团队,直到新特性被集成(在我们的例子中是 Main)。
当我们完成一个新功能(并且分支已合并到 Main)时,我们将分支移动到分支历史文件夹中。这使开发人员需要查看的分支(文件夹)数量保持在最低限度。
在我们的例子中,没有人在 Main 分支工作。所有开发都在功能分支中完成。初始开发(在第一次发布到生产之前)在开发分支中完成。在第一次发布到生产后,所有开发都在一个新的功能分支中完成。
如果你有一个中小型团队,那么当你真的不需要完全分支隔离时避免额外的分支......特别是如果你的开发团队的文化反对正确分支和合并。也许为了换取更少的分支来维护,确保所有被允许进行合并的开发人员都虔诚地遵循合并实践。Shelvesets(在 TFS 中)和短期特性分支是很好的技术,可以最大限度地减少合并开销和相关风险。
这是我发现的一种模式,可以平衡生产力和版本控制安全性(对于约 25 名开发人员和约 3 名测试人员的团队):
在同一个分支中工作:开发松散耦合或不相关代码的开发人员可以相对安全地直接在同一个开发(或“集成”)分支中工作。错误修复和非破坏性更改非常适合这里(降低主要回归影响其他开发人员的风险)。持续集成构建和门控构建是降低许多开发人员在同一分支工作的风险的两个最佳实践。 切换注意:功能切换可用于进一步避免需要分支,但确保测试/维护切换行为的开销不会比使用分支风险更大。
Shelvesets:使用您的版本控制系统的功能来保存特定于开发人员的原型分支中的未决更改。签入 TFS(Team Foundation Server)的开发人员可以使用搁置集而不是个人分支(或许多微功能/任务分支),如果他们是唯一需要在签入集成/开发分支之前开发和测试功能的人. 我相信其他版本控制系统也有类似 的结构只工作。)
短期分支:当您确实需要一个用于隔离的分支(例如多个开发人员需要处理的破坏性功能)时,创建短期功能分支是一种好方法。我推荐一个分支命名约定,使分支的使用随着时间的推移保持良好的定义和唯一性。
上述工作流程的主要优点是它最大限度地减少了合并税(向前/向后集成(向下/向上合并)所花费的时间),而不是开发直接提高客户满意度的功能。
示例场景:新的“酷”功能将破坏现有功能并构建直到完成。它还需要 2 个以上的开发人员在相同的代码库上进行协作(消除使用 Shelveset 的选项)。“Cool”的开发所有者创建名为Cool1的分支,然后开发和集成测试功能的第一个版本。开发所有者负责每天(最多每周一次)合并父级更改。确认准备好合并(父合并做子(FI),所有 UT 和核心验收测试运行并仍然通过)。合并到父 (RI),然后确认父分支中的工作(所有 UT 和核心验收测试通过),然后删除Cool1功能分支(清理)。
合并到 dev/integration 分支后更彻底地测试 Cool 功能。(测试资源有限,因此避免每个分支都使用完整的测试环境。)Cool 的错误修复和战术增强/重构将直接在 Dev 分支中完成(当分配的开发人员需要很多天才能在签入前进行本地化开发/测试时,使用搁置集)。如果稍后需要对 Cool 进行重大(多开发人员)返工,则创建一个新的Cool2分支。
TFS2010 移动/重命名 注意: TFS 2010 移动和重命名行为已更改(从 TFS 2008 开始)以进行移动和重命名 =“分支到新名称/位置,然后将原始项目标记为已删除”。这意味着如果您不想在源代码管理 \Dev\ 中看到它们,您应该只删除不活动的功能分支,而不是将分支移动到不同的文件夹。这也意味着启用查看已删除文件夹的开发人员将始终将这些已删除(或移动或重命名)的短期分支视为可能会变得混乱的“幽灵”。(这就是您可以查看历史记录或取消删除已删除项目的方式。)
功能分支的替代方法是功能切换(即代码中可以使功能可用或不可用的开关)。它们在这方面非常有用。他们可以允许开发和部署新功能,但只有在切换...良好切换(甚至是一个词)时才可用。我想这就像整个谷歌实验室的想法。
这里要注意的一点是,如果在开发过程中没有仔细考虑和测试这些切换,它们本身也会引起戏剧性的影响。实际上,您正在增加您需要执行的测试量,以查看启用和禁用功能的情况。如果您有多个功能正在开发中,那么您需要了解它们如何与启用/禁用状态的各种组合进行交互。
话虽如此,如果做得好,它们也会带来很大的好处。您可以向某些用户(高级用户或该功能的拥护者等)发布一项功能,而不会影响所有人。如果认为它引起了问题,则可以通过更改存在某些配置元素的 DB 记录来将其关闭。
一旦给定的功能被认为已通过集合,建议删除切换并将其作为整个应用程序的一部分。
话虽如此,我不认为功能分支不好,但它确实依赖于每个人都理解源代码控制和合并的概念,并确保分支不会与主分支过于脱节而导致大量 OMG 类型合并。
我最近参加了由 Thoughtworks 主办的一次会议,Martin Fowler 讨论了这个话题。演讲的重点是持续交付以及这如何帮助克服缓慢且有风险的部署。请参阅http://www.thoughtworks.com/events/thoughtworks-continuous-delivery-devops或搜索持续交付以获取更多信息。
使用自己的分支处理合并目标的团队越多,您的沟通就需要更好地处理冲突。
警惕代码中的高流失、耦合和公共区域。这些将是争论的领域。
在 TFS 中可以有效地按功能进行分支,但与 dev 中的任何事情一样,越复杂,您获得的开销就越多。
Git比TFS好得多。我已经使用 git 超过 7 年了,在此之前使用过 TFS。最近我换了工作,我必须使用 TFS。仅仅拥有一个 dev 分支并且所有开发人员都在同一个 dev 上工作并不能提供任何适当的审查机会。我喜欢 git 代码审查是一个正式的过程这一事实。
使用 git,我通过创建与功能/工作项相关的分支来处理本地分支。完成工作后,您可以将其推送到远程分支。然后,您将从远程分支向您的开发/集成分支发出拉取请求。一旦拉取请求被审查,审查者会将 PR 合并到 dev 分支。这对我来说非常有效。