被Git Flow折磨两年,换主干开发后真香

还记得两年前那个黑色的周五下午,离下班还有半小时。

当时我们的后端兄弟“大刘”正准备把开发了两周的“双十一促销功能”分支合并回 develop 分支。由于这两周内其他同事已经合入了四十多次代码,大刘对着满屏红色的 Merge Conflicts 绝望地抓头。那天我们整个小组为了解冲突、修因合并产生的回归Bug,硬是加班到了凌晨两点。

那时我一直以为,严格遵守 Vincent Driessen 提出的 Git Flow(也就是那张经典的、像地铁线路图一样的分支模型),是团队走向正规化的必经之路。

直到后来我带着团队转型 主干开发(Trunk Based Development),我才发现:对于大多数中小团队来说,过度的流程不是保护,而是累赘。

今天就和大家聊聊,我们是如何从Git Flow的泥潭里爬出来,通过主干开发让上线效率翻倍的实战经历。

以为是规范,其实是枷锁:Git Flow 的“过度设计”

配图

刚开始带团队时,为了显得“专业”,我强制要求大家严格执行 Git Flow。我们在 GitLab 里锁定了 masterdevelop,每个人开发新功能必须切 feature 分支,测试切 release 分支,修线上Bug切 hotfix 分支。

看起来井井有条,但跑了半年,痛点全暴露了:

  1. “合并地狱”常态化:就像开头提到的大刘,Feature 分支存活时间越长,和主干的差异就越大。最后合并的那一刻,就是风险爆发的时候。
  2. 发布流程极其繁琐:有时候只是改两行代码的文案,却要走一遍 feature -> develop -> release -> master 的全套流程,还要打 Tag。大家为了省事,开始攒一堆小改动一起发,结果导致“每次上线都像开盲盒”,一旦出问题,回滚都不知道回滚哪个commit。
  3. 虚假的隔离:我们以为在 feature 分支上隔离开发很安全,但实际上代码隔离意味着问题隔离。Bug 被藏在分支里,直到上线前集成测试时才炸雷。

当时我们复盘了一下数据:平均每个Feature分支的生命周期长达 5.5 天,而每次发布前的代码冻结和修复时间平均需要 1 天。

对于一个只有 8 个开发人员、需要快速迭代的 SaaS 产品来说,这简直是灾难。

配图

拥抱主干开发:每天上线5次的快乐

痛定思痛,我决定在核心业务线尝试 主干开发(Trunk Based Development,TBD)

简单说,就是团队只维护一条主干分支(通常是 mainmaster)。开发人员的所有代码,要么直接提交到主干,要么在极短命的 Feature 分支(存活不超过24小时)上开发完迅速合入主干。

刚提出这个方案时,团队炸锅了。

配图

“直接往主干合?万一代码没写完,把线上搞挂了怎么办?”

这是最真实的担忧。为了解决这个问题,我们引入了一个关键技术手段:特性开关(Feature Toggles)

这招真的太好用了。我们不再依赖“物理分支”来隔离未完成的功能,而是用“逻辑开关”来隔离。

举个实际代码的例子,比如我们在做新的“用户积分中心”:

# 伪代码示例:利用配置文件或数据库里的开关状态
def get_user_dashboard(user_id):
    # 检查开关是否对当前用户开启
    if feature_flags.is_on('new_point_system', user_id):
        return render_new_dashboard(user_id)
    else:
        # 开关没开,或者是旧版本,跑老逻辑
        return render_legacy_dashboard(user_id)

即便这段代码有了Bug,只要开关是关的,线上用户就完全无感知。

转型后的真实变化:

  • 小步快跑:大刘不再憋两周的大招了。他把“促销功能”拆成了后端接口、数据库变更、前端页面的骨架等 8 个小任务。每天合并 2-3 次代码进主干,每次只改动几十行。
  • 冲突几乎消失:因为大家都在频繁同步主干代码,冲突通常只有一两行,顺手就修了,根本不需要专门停下来解冲突。
  • 随时可发布:主干随时处于可发布状态(Deployable)。周五下午 5 点上线?没问题,因为今天的改动非常小且经过了自动化测试。

实行主干开发三个月后,我们的平均上线频率从“每周1次”变成了“每天4-5次”,而线上故障率反而下降了 40%。

别盲目跟风,适合才是最好的

看到这里,你可能想马上回去推翻现在的流程。但在动手前,请先冷静一下。 这两年踩过的坑告诉我,没有绝对正确的策略,只有适合场景的策略。

我也见过有的团队盲目切主干开发,结果因为没有自动化测试,主干天天挂,甚至被称为“主干崩溃开发”。

怎么选?我总结了一套简单的判断逻辑:

建议继续使用 Git Flow (或 GitHub Flow) 的场景:

  • 开源项目:你不认识贡献者,必须通过 Pull Request 严格审查每一行代码。
  • App 客户端开发:发版成本极高(要过应用商店审核),不能随时回滚,需要极度严谨的 Release 分支验证。
  • 基础设施薄弱:如果你的团队没有自动化测试(Unit Test / CI),代码一合就炸,那 Git Flow 的繁琐流程反而是你们的“安全气囊”。

强烈建议切换到 主干开发 的场景:

  • SaaS / Web 后端 / H5:具备随时回滚的能力。
  • 中小团队 (3-15人):沟通成本低,追求极致的交付速度。
  • DevOps 能力较强:有完善的 CI/CD 流水线,代码提交后能自动跑测试。

我个人的习惯是:凡是能通过自动化解决的,绝不依赖人工流程。 Git Flow 很多时候是在用繁琐的人工流程来弥补技术自信的不足。

总结与行动

回看这两年,从 Git Flow 到主干开发的转变,本质上是一场信任机制的转变:从“我不信任你的代码,所以要隔离你”,变成了“我信任我们的测试体系,所以允许你快速合并”。

如果你也想尝试改进分支策略,建议从以下 3 个具体的行动开始,别贪多:

  1. 搭建基础 CI 门禁:不要裸奔。至少在 GitLab/GitHub 里配置一个简单的 Pipeline,确保代码 Merge 进主干前,自动运行 Lint 检查和单元测试。这是主干开发的底裤。
  2. 强制拆分任务:在早会(Stand-up)上定个规矩:任何任务如果预估超过 1 天才能合并,必须拆分。强迫大家习惯“提交半成品”(配合特性开关)。
  3. 定期大扫除:我每周五下午会花 15 分钟清理远程仓库里那些超过 1 个月没动静的僵尸分支。干干净净的仓库,看着心情都好。

你在团队中遇到过最惨烈的“代码合并事故”是什么样的?现在的你们是在用 Git Flow 还是其他路子?

欢迎在评论区和我聊聊,说不定你的方案能给更多人启发。