译者 | 刘汪洋
审校 | 重楼
如今,分布式版本控制系统,例如 Git,在版本控制领域已然成为主流。有人认为,使用像 Git 这样的版本控制系统(VCS)进行分支和合并非常便捷。但我更推崇基于主干的开发(TBD),现在我将解释其中的原因。
在基于主干的开发模式中,所有开发人员都在同一个分支(例如 'mAIn')上工作。你可能已经从 Martin Fowler 或 Dave Farley 那里了解过相关讨论。当 Git 迅速成为首选版本控制系统时,通过与 Dave 的合作经历,我亲身体验到了团队在持续交付环境中基于主干开发所带来的优势。
与此不同,分支模型则鼓励开发人员为每个特性、错误修复或增强功能创建独立的分支。虽然分支在隔离变动和降低风险方面看似合理,但许多因素让我更倾向于基于主干的开发方式。
主干开发模式下,整个团队在同一分支上协作,从而实现更迅速的集成,并减少合并冲突。这正是持续集成(CI)的核心理念。虽然现在提到 CI 时通常是指“每次提交时在团队服务器上运行构建和测试”,但CI的本质是确保代码能够定期并顺利地集成。独立分支的代码未集成,且存在时间越长,合并回主代码库的难度越大。独立分支上快速开发的修复和改进似乎很迅速,但最终还是有代价的。定期集成小的更改通常比长时间后进行大型合并更为轻松。
主干开发鼓励频繁提交,从而产生小型、易于管理的更改。频繁拉取其他开发人员的更改,并推送小型、有效的代码更改,有助于确保代码库的稳定性和可用性。如果有 CI 服务器为每次提交运行构建和测试,验证这种“稳定和可工作”的假设就更方便了。任何时候构建中断,我们必须暂停提交,专注于修复。在构建中断时持续推送更改将无益于任何人。
在分支模型下,庞大、不频繁的合并可能会因更改的规模而难以定位和修复错误。当他人合并了大型工作后,你是否曾发现自己的代码不再工作?如果你和他人做了许多不同或重叠的更改,找出导致测试失败或应用程序工作不正常的原因可能会耗费很长时间,而这还需要你有可靠的测试覆盖率。
结对编程是我最喜欢的团队成员之间的知识共享方式,虽然我知道并不是每个人都能这样做(有关此方面的更多信息,可以查看 JetBrains 的 Code With Me)。如果没有配对,至少团队应该在同一代码上工作。如果每个人都在自己的分支上工作,那么他们其实是在相互竞争而非协作,还可能会因为担心被他人的更改压倒而过于小心翼翼。
若团队都在同一分支上工作,通常会增进对正在进行更改的理解,促进团队协作和知识共享。相反,分支可能造成孤立的工作环境,导致团队内部的知识空白。
Dave Farley 的书籍 “持续交付”,以及相关博客文章和视频,都深入强调了“主干开发模式与持续集成和持续交付(CI/CD)实践的天然相容性”。
在主干开发模式下,持续集成的实施更加直接,因为代码会频繁提交到主干分支,而这也正是 CI 环境所构建和测试的分支。任何的失败都能及时发现并解决,从而降低了重大故障的风险。通常,追踪引起问题的具体更改相对容易。如果某个问题无法立即解决,可以回退导致该问题的具体修改。
现在我们应该明白快速反馈循环的价值,因为它能让我们更快地发现问题、找到原因,并迅速修复,从而提升软件的质量。
在主干开发环境中,持续交付也得以蓬勃发展。成功的持续交付要求始终保持代码库可部署的状态。主干开发方法通过促进频繁的提交、集成,以及对所有集成的全面测试,确保了这一目标的实现。任何时候引入的细微修改都使得软件部署和测试更为顺畅。
相较之下,使用分支模型来实现有效的 CI/CD 往往更复杂、更耗时。虽然有人可能会认为:“我可以在我的分支上运行构建和所有测试”,但实际情况是,并非每次提交都进行了真正的集成。直到合并(或变基)的过程中,你才会开始面对任何集成问题。在分支上运行的所有测试,并没有对任何类型的集成进行实际检验。
合并和测试不同分支的代码可能会引入延迟和潜在错误,进而削弱构建流水线的某些优势。
长期维护的分支常造成“合并地狱”现象,这是由于主分支(例如 'main')与特性分支之间的差异过大,导致合并过程变得异常困难。这种情况可能引发技术债务的累积,因为解决合并冲突时可能会采用快速但非理想的修复方案,或者接受集成开发环境(IDE)的自动建议而可能对其并未完全理解。相较之下,主干开发、频繁的合并操作和较小的代码更改则使技术债务的管理和减少变得更为便捷。
我个人确信主干开发具备显著优势,并在实际项目中亲自体验了采用此种方法的团队效益。然而,这需要团队共同建立一种思维方式和文化氛围。这其中涉及频繁合并他人的代码更改,经常进行小规模的代码修改,按部就班地进行增量改动。这可能是一种需要适应的开发习惯。整个团队采用一致的方法和文化,关键在于实践配对编程、全面自动化测试和进行适当的代码审查。
有序、纪律的主干开发能简化流程,增强协作,提升代码稳定性,支持CI/CD实践,并减轻技术债务。如果你一直采用基于分支的模型,转变可能会面临挑战,但从长期来看,优势是明显的。若你对此感兴趣,还可以参阅Dave的文章,他在其中解释了主干开发的障碍。
版本控制分支、提交、主干开发、持续集成/部署等是软件开发过程中的关键概念。
刘汪洋,51CTO社区编辑,昵称:明明如月,一个拥有 5 年开发经验的某大厂高级 JAVA 工程师,拥有多个主流技术博客平台博客专家称号。
原文标题:Why I Prefer Trunk-Based Development,作者:Trisha Gee