<audio id="audio" title="04 | 一切的源头，代码分支策略的选择" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/52/ce/52565d5de9b66f1f25c64ccc8b68d4ce.mp3"></audio>

记得大概是一年前吧，我与好友老吴喝茶聊天时，讨论到：高效的持续交付体系，必定需要一个合适的代码分支策略。

我告诉老吴：“采用不同的代码分支策略，意味着实施不同的代码集成与上线流程，这会影响整个研发团队每日的协作方式，因此研发团队通常会很认真地选择自己的策略。”

老吴是一名有多年开发经验的资深架构师，当时正好要接手一个框架团队，从个人贡献者向团队管理者转型。他个人对代码管理工具可谓熟之又熟，甚至连“老古董”的CVS都可以跟你聊半天。但他在为团队制定代码分支管理策略时，还是慎之又慎，足见其重要性。

最后我们发现，要确定选用哪种代码分支管理策略，需要先假设几个问题，这几个问题有了答案，也就代表你找到了适合的方向。

你需要思考的几个问题如下：

<li>
Google和Facebook这两个互联网大咖都在用主干开发（Trunk Based Development，简称TBD），我们是不是也参照它俩，采用主干开发分支策略？
</li>
<li>
用Google搜索一下，会发现有个排名很靠前的分支策略，叫“A successful Git branching model”（简称 Git Flow），它真的好用吗？团队可以直接套用吗？
</li>
<li>
GitHub 和 GitLab 这两个当下最流行的代码管理平台，各自推出了 GitHub Flow 和 GitLab Flow，它们有什么区别？适合我使用吗？
</li>
<li>
像阿里、携程和美团点评这样国内知名的互联网公司，都在用什么样的分支策略？
</li>

今天，我想再沿着当时的思考路径，和你一起回顾和总结一下，希望能够带你全面了解代码分支策略，帮助你做出合适的选择。

## 谈谈主干开发（TBD）

**主干开发是一个源代码控制的分支模型，开发者在一个称为 “trunk” 的分支（Git 称 master） 中对代码进行协作，除了发布分支外没有其他开发分支。**

Google和 Facebook都是采用“主干开发”的方式，代码一般直接提交到主干的头部，这样可以保证所有用户看到的都是同一份代码的最新版本。

**“主干开发”确实避免了合并分支时的麻烦，因此像Google这样的公司一般就不采用分支开发，分支只用来发布。**

大多数时候，发布分支是主干某个时点的快照。以后的改Bug和功能增强，都是提交到主干，必要时 cherry-pick （选择部分变更集合并到其他分支）到发布分支。与主干长期并行的特性分支极为少见。

由于不采用“特性分支开发”，所有提交的代码都被集成到了主干，为了保证主干上线后的有效性，一般会使用特性切换（feature toggle）。特性切换就像一个开关可以在运行期间隐藏、启用或禁用特定功能，项目团队可以借助这种方式加速开发过程。

特性切换在大型项目持续交付中变得越来越重要，因为它有助于将部署从发布中解耦出来。但据吉姆 · 伯德（Jim Bird）介绍，特性切换会导致代码更脆弱、更难测试、更难理解和维护、更难提供技术支持，而且更不安全。

他的主要论据是，将未经测试的代码引入生产环境是一个糟糕的主意，它们引发的问题可能会在无意间暴露出来。另外，越来越多的特性切换会使得逻辑越来越混乱。

**特性切换需要健壮的工程过程、可靠的技术设计和成熟的特性切换生命周期管理**，如果不具备这三个关键的条件，使用特性切换反而会降低生产力。

根据上面的分析，主干开发的分支策略虽然有利于开展持续交付，但是它对开发团队的能力要求也更高。

主干开发的优缺点如表1所示。<br>
<img src="https://static001.geekbang.org/resource/image/59/5e/59096cdc19f9e0a5fefbe99f9b57445e.png" alt="">

## 谈谈特性分支开发

和主干开发相对的是 “特性分支开发” 。在这个大类里面，我会给你分析Git Flow、GitHub Flow和 GitLab Flow这三个常用的模型。

**第一，Git Flow**

我们在Google上查关键词“branch model”（也就是“分支模型”），有一篇排名比较靠前的文章“A successful Git branching model”，它介绍了Git Flow模型。

Git刚出来的那些年，可参考的模型不多，所以Git Flow模型在2011年左右被大家当作了推荐的分支模型，至今也还有项目团队在使用。然而，Git Flow烦琐的流程也被许多研发团队吐槽，大家普遍认为hotfix和 release 分支显得多余，平时都不会去用。

<img src="https://static001.geekbang.org/resource/image/4b/0f/4bc4c4035857479b2126fed5af4ce90f.png" alt="">

**第二，GitHub Flow**

GitHub Flow 是 GitHub 所使用的一种简单流程。该流程只使用master和特性分支，并借助 GitHub 的 pull request 功能。

<img src="https://static001.geekbang.org/resource/image/7a/14/7ae8a5fe4f5fcdae7ba9cfaf758f1a14.png" alt="">

**在 GitHub Flow 中，master 分支中包含稳定的代码，它已经或即将被部署到生产环境。任何开发人员都不允许把未测试或未审查的代码直接提交到 master 分支。对代码的任何修改，包括Bug 修复、热修复、新功能开发等都在单独的分支中进行。不管是一行代码的小改动，还是需要几个星期开发的新功能，都采用同样的方式来管理。**

当需要修改时，从 master 分支创建一个新的分支，所有相关的代码修改都在新分支中进行。开发人员可以自由地提交代码和提交到远程仓库。

当新分支中的代码全部完成之后，通过 GitHub 提交一个新的 pull request。团队中的其他人员会对代码进行审查，提出相关的修改意见。由持续集成服务器（如 Jenkins）对新分支进行自动化测试。当代码通过自动化测试和代码审查之后，该分支的代码被合并到 master 分支。再从 master 分支部署到生产环境。

GitHub Flow 的好处在于非常简单实用，开发人员需要注意的事项非常少，很容易形成习惯。当需要修改时，只要从 master 分支创建新分支，完成之后通过 pull request 和相关的代码审查，合并回 master 分支就可以了。

**第三，GitLab Flow**

上面提到的GitHub Flow，适用于特性分支合入master后就能马上部署到线上的这类项目，但并不是所有团队都使用GitHub或使用pull request功能，而是使用开源平台GitLab，特别是对于公司级别而言，代码作为资产，不会随意维护在较公开的GitHub上（除非采用企业版）。

GitLab Flow 针对不同的发布场景，在GitHub Flow（特性分支加master分支）的基础上做了改良，额外衍生出了三个子类模型，如表2所示。<br>
<img src="https://static001.geekbang.org/resource/image/0e/34/0efbe615c847aac070fdb9b8a588a434.png" alt="">

<img src="https://static001.geekbang.org/resource/image/8e/1e/8e29bb4314de4492977e919abe91191e.jpg" alt="">

<img src="https://static001.geekbang.org/resource/image/bd/c8/bd6218d57b6d522844cf080d9ca9a7c8.jpg" alt="">

<img src="https://static001.geekbang.org/resource/image/1b/58/1bf962fe8b0523fefac348529ffc0d58.jpg" alt="">

GitLab Flow的特性分支合入master用的是“Merge Request”，功能与GitHub Flow的“pull request”相同，这里不再赘述。

通过Git Flow、GitHub Flow和 GitLab Flow（3个衍生类别） 这几个具体模型的介绍，我给你总结一下特性分支开发的优缺点。如表3所示。

<img src="https://static001.geekbang.org/resource/image/a5/b1/a517f2b1c48c8de54e500df3996628b1.png" alt="">

## 选出最适合的分支策略

上面我跟你讲到的分支模型，都是IT研发领域比较流行的。虽然有些策略带上了代码平台的标识，如GitHub Flow，但并不意味着该策略仅限于GitHub代码平台使用，你完全可以在自己搭建的代码平台上使用这些策略。

接下来，我就总体归纳一下什么情况下应该选择什么样的分支策略。如表4所示。<br>
<img src="https://static001.geekbang.org/resource/image/ae/d9/ae29f0b5a96306f49ce485c1823b23d9.png" alt="">

## 国内互联网公司的选择

GitLab作为最优秀的开源代码平台，被多数互联网大公司（包括阿里、携程和美团点评等）所使用，这些大厂也都采用特性分支开发策略。当然，这些大公司在长期持续交付实践中，会结合各自公司的情况做个性化的定制。

比如，携程公司在GitHub Flow的基础上，通过自行研发的集成加速器（Light Merge）和持续交付Paas平台，一起完成集成和发布。

再比如，阿里的AoneFlow，采用的是主干分支、特性分支和发布分支三种分支类型，再加上自行研发的Aone协同平台，实现持续交付。

## 总结

今天，我主要给你介绍了各种代码分支策略的特性。

你应该已经比较清晰地理解了“主干开发”和“特性分支开发”两种策略的各自特性：

<li>
“主干开发”集成效率高，冲突少，但对团队个人的开发能力有较高要求；
</li>
<li>
“特性分支开发”有利于并行开发，需要一定的流程保证，能保证主干代码质量。
</li>

相信在没有绝对自信能力的情况下，面对绝大多数的场景，企业还是会选择“特性分支开发”的策略。所以，我给你介绍了几种主流的特性分支方法，并对比了各类策略的优劣，以及它们适用的场景。

接下来，你就可以根据自己所在项目的具体情况，参考今天的内容，裁剪出最适合自己团队的分支策略了。

## 思考题

<li>
开源性质的项目，为什么不适合用主干开发的分支策略？
</li>
<li>
如果你所在的团队只有5人，而且迭代周期为1周，你会采用什么样的分支策略？
</li>

欢迎你给我留言。


