我已经使用 Git Flow 构建我的 Git 分支有几年了。但是,我遇到了 Git Flow 的一些问题,其中大部分来自长期存在的分支。解决这些问题的方案就是 Trunk Based Development。这是一个非常简单的技术,也是有效的持续交付的基础。在这篇文章中,我会告诉你我是如何通过 HolidayCheck 的 IOS 开发团队从 Git Flow 过度到 Trunk Based Development 的开发的。您将了解最重要的步骤,以及从 Trunk Based Development 中获得的好处,请继续阅读。
Git Flow 的问题
合并冲突
合并冲突在使用 Git Flow 是非常常见。原因很简单:如果你有多个并行功能分支,他们长时间存在,那么很可能在代码库的相同部分在两个不同的分支中被更改。合并冲突不仅对于需要手动解决的开发人员来说是令人沮丧的。这也增加了在代码中破坏某些功能的风险,因为当你不得不决定使用哪个版本代码时,很容易犯错。即使你把一个分支合并到另一个分支时你做的都是正确的,可能也会发生这两个特性的组合影响了你的代码。
构建
功能分离
在合并到一个分支之前,你是不能测试两个功能的组合。当你在单独的分支机构中开发几天甚至几周的功能时,由于两个功能的相互作用而产生的问题发生了。当你对这些问题反映迟缓时,你可能不得不改变你为新功能编写的代码的更多部分。这意味着你已经浪费了很多的时间来创建你不再需要的代码。
许多不同的功能分支也可能会让你的软件的手动测试人员感到困惑。他们总是必须知道在哪个临时环境中可以找到新功能。不同的阶段环境通常也意味着不同的构建任务,用于监控任务的不同屏幕等。
不可预测的发布
Git Flow 还有另一个问题,这是以上两点的结果:如果功能分支尚未合并,则不可能知道需要多少时间才能发布。你不知道它是因为你不知道哪个合并会发生冲突,你也不知道新功能将如何相互影响。不能在任何时候发布将使你缺乏信心。
解决方案
Trunk Based Development
好消息!上述所有问题都有解决方案,就是Trunk Based Development。你只有一个主分支,即主干(Master 或者 Mainline)。不再有开发分支,也没有存在时间很久的分支。所有的提交都会尽快合并到主干中,至少每天一次。通过如此迅速的合并到主干,合并冲突变的非常罕见。使用短时间分支是避免合并冲突的4个简单技巧之一。即使你遇到了合并冲突,也可能很容易解决,因为从上次合并到主干后变化并不那么大。不同功能之间的干扰立即可见,可以在功能正在进行时测试。
基于主干的开发也将鼓励你的团队以小的 Step 思考和工作,从而做到小的提交,这些提交可以快速合并到主干。通常,小 Step 可以减少错误数量,并有助于创建模块化设计。
最大的问题时:如果每天将代码推送到一个不稳定的主干,即使某个功能还没有完成,你如何才能避免出现有问题的主干?请接着阅读来寻找答案。
如何从 Git Flow 到 Trunk Based Development 功能切换
功能切换
当我在 HolidayCheck 向我的团队介绍 Trunk Based Development 的开发时,为了能够迅速的将代码提交到主干,有一个第一步是绝对必要的!在开始我们的分支结构之前,我们必须确保我们使用能够尽快的融入开发分支的并且存在时间很短的分支。解决办法相当简单,我们开始使用功能切换——源码中的一些开关决定功能是否处于活动状态。
只要功能没有准备好被发布,它就会被禁用。这使我们可以在不破坏任何东西的情况下将其推入到开发分支。开发人员和手动测试人员可以在一些设置中启用对于普通用户隐藏的每个功能。开发分支随时准备被发布,因为未完成的功能将被关闭。他们将被推送到客户,但是是不可见状态的。一旦某个功能完成,他就会打开并在下一个版本中可用。
当我们在代码中切换这些功能时,我们意识到它们不仅在功能开发的时候有用!即使功能完成,在代码中保持切换也是非常好的。如果我们有可能为所有用户远程控制切换,那么只要我们发现他对我们的转化率或其他关键数字有不良影响,我们就可以快速停用该功能。此外,如果发生任何错误或者服务器的流量负载过高,我们总是能够立即关闭该功能。这一点尤其重要,因为我们必须等待多天,直到苹果回顾,出了我们的 IOS 应用程序的新版本。能够在没有新版本的情况下禁用功能是一个非常强大的武器。
现在,随着所有功能的切换,我们还可以做另一件伟大的事情:A/B 测试!由于每个功能都可以随着远程控制,所以我们可以只为部分用户群启用某项功能,并禁用其他功能。这样做,我们可以看到一个功能真正的执行。我们可以在小测试组上测试新功能,然后决定是否应该为每个人启用它,或者如果我们看到负面影响将其删除。我们使用 Optimizely 来控制和评估我们的 A/B 测试,但也有其他工具可用。
一个分支约定所有
现在我们可以快速地将我们的功能分支合并到开发分支中(因为未完成的功能已经停用),我们可以随时发布开发分支。问题是:我们是否还需要一个开发和一个主分支?答案是:不需要。我们可以直接把所有东西都交给 Master 而不是 Develop 分支。Master 随时准备投入生产(不要忘记每当有东西被推入 Master 时,都要运行所有的测试)。如果我们想创建一个发行版本,我们可以直接从主分支创建,或者为此创建一个发行版分支。最新发布的提交标有 Git tag。所以引入功能切换后的第二步是删除开发分支!在这里,我们已经是 Trunk Based Development!
总结
Trunk Based Development 使我的团队更加灵活。我们可以随时发布我们的主分支,我们已经没有大的合并冲突了。总是随时准备投入生产的主分支是持续交付的先决条件。功能切换是 A/B 测试的先决条件。它们帮助我们了解客户真正想要什么,并使我们更有信心,因为我们知道可以随时禁用某个功能。结果就是:风险更小,创新更多。
JFrog 中国研发工程师,曾在唯品会担任研发工程师,擅长 Java,参与过多个互联网平台的研发和运维工作,现专注于Devops 落地,持续集成、持续交付领域。
原文作者:Robert 原文地址: https://team-coder.com/from-git-flow-to-trunk-based-development/
为什么我从 Git Flow 开发模式切换到了 Trunk Based 开发模式?
原文地址:http://jfrogchina.blog.51cto.com/13458615/1981238