git-flow问题

上述所有问题都有解决方案,就是Trunk Based Development。你只有一个主分支,即主干(Master 或者 Mainline)。不再有开发分支,也没有存在时间很久的分支。所有的提交都会尽快合并到主干中,至少每天一次。通过如此迅速的合并到主干,合并冲突变的非常罕见。使用短时间分支是避免合并冲突的4个简单技巧之一。即使你遇到了合并冲突,也可能很容易解决,因为从上次合并到主干后变化并不那么大。不同功能之间的干扰立即可见,可以在功能正在进行时测试。

基于主干的开发也将鼓励你的团队以小的 Step 思考和工作,从而做到小的提交,这些提交可以快速合并到主干。通常,小 Step 可以减少错误数量,并有助于创建模块化设计。

最大的问题时:如果每天将代码推送到一个不稳定的主干,即使某个功能还没有完成,你如何才能避免出现有问题的主干?

TBD

Trunk Based Development,缩写为TBD,中文就是基于主干的开发。
什么是TBD,无需太多文字,看下图即可(来源http://paulhammant.com/2013/04/05/what-is-trunk-based-development/):

Paul Hammant 2013年提出的模型,这个模型不用多解释,基本就是SVN的模型,在TBD模型中,所有开发都在主干,但是拉出新的分支交付。这个场景下,假设所有的特性开发都可以快速完成,这样就不会影响CI
image.pngimage.png

如何从 Git Flow 到 Trunk Based Development 功能切换

功能切换
当我在 HolidayCheck 向我的团队介绍 Trunk Based Development 的开发时,为了能够迅速的将代码提交到主干,有一个第一步是绝对必要的!在开始我们的分支结构之前,我们必须确保我们使用能够尽快的融入开发分支的并且存在时间很短的分支。解决办法相当简单,我们开始使用功能切换——源码中的一些开关决定功能是否处于活动状态。
image.png

只要功能没有准备好被发布,它就会被禁用。这使我们可以在不破坏任何东西的情况下将其推入到开发分支。开发人员和手动测试人员可以在一些设置中启用对于普通用户隐藏的每个功能。开发分支随时准备被发布,因为未完成的功能将被关闭。他们将被推送到客户,但是是不可见状态的。一旦某个功能完成,他就会打开并在下一个版本中可用。

当我们在代码中切换这些功能时,我们意识到它们不仅在功能开发的时候有用!即使功能完成,在代码中保持切换也是非常好的。如果我们有可能为所有用户远程控制切换,那么只要我们发现他对我们的转化率或其他关键数字有不良影响,我们就可以快速停用该功能。此外,如果发生任何错误或者服务器的流量负载过高,我们总是能够立即关闭该功能。这一点尤其重要,因为我们必须等待多天,直到苹果回顾,出了我们的 IOS 应用程序的新版本。能够在没有新版本的情况下禁用功能是一个非常强大的武器。

现在,随着所有功能的切换,我们还可以做另一件伟大的事情:A/B 测试!由于每个功能都可以随着远程控制,所以我们可以只为部分用户群启用某项功能,并禁用其他功能。这样做,我们可以看到一个功能真正的执行。我们可以在小测试组上测试新功能,然后决定是否应该为每个人启用它,或者如果我们看到负面影响将其删除。我们使用 Optimizely 来控制和评估我们的 A/B 测试,但也有其他工具可用。

一个分支约定所有
现在我们可以快速地将我们的功能分支合并到开发分支中(因为未完成的功能已经停用),我们可以随时发布开发分支。问题是:我们是否还需要一个开发和一个主分支?答案是:不需要。我们可以直接把所有东西都交给 Master 而不是 Develop 分支。Master 随时准备投入生产(不要忘记每当有东西被推入 Master 时,都要运行所有的测试)。如果我们想创建一个发行版本,我们可以直接从主分支创建,或者为此创建一个发行版分支。最新发布的提交标有 Git tag。所以引入功能切换后的第二步是删除开发分支!在这里,我们已经是 Trunk Based Development!

总结
Trunk Based Development 使我的团队更加灵活。我们可以随时发布我们的主分支,我们已经没有大的合并冲突了。总是随时准备投入生产的主分支是持续交付的先决条件。功能切换是 A/B 测试的先决条件。它们帮助我们了解客户真正想要什么,并使我们更有信心,因为我们知道可以随时禁用某个功能。结果就是:风险更小,创新更多

特点

从以上需求,情景出发,我们可以将主干开发做个小结

优势:

  • 只有一个长期存在的分支,容易理解,易于实施
  • 强调人的主动性,以人为本
  • 强调团队协作,而不是监管审查
  • 测试内嵌、自动化,质量有保障
  • 随时交付价值,贴近客户

劣势:

  • 线上版本会引入未完成的代码
  • 关于线上引入未完成代码的劣势,这里提供一个解决方案及实践 - Feature Toggle(特性开关):

所有的feature toggle因该是短生命周期的,有创建,有消亡, 用相应的工具去管理这些feature toggle的生命周期

可以看出,分支开发和主干开发各有所长,我们在做具体选择的时候是否需要关心以客户为中心,以人为本,持续交付价值。

总结

主干开发的要求:
1. 每天向主干合并一次代码
2. 让分支生命周期尽量短(少于一天)
3. 同一时间少于三条的活跃分支

高效能和低效能团队的分支策略差异十分明显:
1. 高效能研发团队拥有最短的集成周期和分支存活时间,普遍持续若干小时
2. 低效能研发团队拥有最长的集成周期和分支存活时间,普遍持续数日

自动化平台支持

image.png[

](https://blog.csdn.net/weixin_32019329/article/details/112528273)


  1. 如何让合并代码不会成为恶梦,不想一合并就有很多冲突

主干开发的关键并不是所有的开发必需在主干上,而在于合并的时机。和长生命周周期分支相反的是,建议小步快跑,频繁提交。也是基于这一点,持续集成(CI),才可能发生。在实际操作中,会要求团队成员每天都提交,最好一天提交多次。当然,提交是有前提条件的,也就是经过自测试,没有问题的代码,才能提交。那么这里的测试最好是自动化,并且耗时较短,比如只用跑单元测试,但重点是都要自动化 — 尽可能自动化一切可以自动化的步骤。如果大家都能频繁提交,当然也会遇到冲突,但这种冲突通常足够小,可以接受,因为提交的量足够小,并且在冲突的时候也可以直接和团队成员沟通,看是否有需要重构的地方,发挥大家的主动性。在每日站会和IPM等其它的敏捷实践流程中,都可以提前发现一些有共性的地方,都可以提前沟通和探讨,共同设计。

  1. 代码为什么要被审核?如果是为了保证质量,是否可以提前告诉我标准,我可以按标准来写,梳理测试用例。如果是想帮助我提高我的代码技能,是否可以提前沟通,我也可以查漏补缺

如上所述,主干开发会有很多机会能和团队发生充分交流,再比如团队的代码review,也会是个很好的机会,方便大家互帮助,给出修改意见。而不用等到最后,有专人审查代码,更别说是平常没有参与项目的人。

  1. 为什么要关心服务的版本号,我只是想查看一下我的工资是否到账了年底了,大家都会收到年度账单,我也想看看我的储蓄卡这一年的账单。如果现在没有,两天后我能不能看到?

从以上两点可以看出,用户是对版本号不敏感的,因为我是想用你的服务帮我解决问题,而不是相对技术的术词 - 版本号。用户的需求变化很快,也想马上就能用上。

如果想要持续交付价值,就需要将已经测试通过的代码,处于随时可以发布的状态,那么这个测试因该是持续的,自动的。所有的这些才能让持续交付价值得以保证。[

](https://blog.csdn.net/weixin_32019329/article/details/112528273)
[

](https://blog.csdn.net/weixin_32019329/article/details/112528273)