Git-分支策略

对分支策略的期望是什么?

这个问题受很多因素的影响,团队的规模,项目团队的数量,项目是否同时开发多个功能,代码发布到生产环境的频率…… 条件越复杂,我们就越需要一个合适的分支策略去支持团队工作。

我们先从简单的需求方案总结我们所期望分支策略做的事,再逐渐复杂化。

首先,作为个体(即使是在个人项目的演示中),我们需要:

  1. 有我们所做更改的全部历史版本
  2. 可以进行修改对比、必要时还原历史版本
  3. 如果我需要创建一个 bugfix ,我可以在不影响我进行中的新功能开发的前提下去开发和部署它

那么,作为团队,除了上述要求,我还需要:

  1. 能够正常工作并推送更改到远程服务器而不影响我的同事们
  2. 可以将我的更改与同事的更改合并,并以最简单的方式解决任何冲突
  3. 无论涉及的人数多少,都要确保代码的质量/基本标准
    这是代码版本控制的基本要求,或者说,是 DevOps 的基本要求。

基本概念

分支策略就是在哪个分支上开发、在哪个分支上部署、分支同步和分支合并的原则。
现代主流的分支策略有

  1. Git Flow(2010年)
  2. GitHub Flow(2011年)
  3. Trunk based development(2013年)
  4. GitLab Flow(2014年)

Git Flow

此工作流,是 Vincent Driessen 2010 年发布出来的他自己的分支管理模型,到现在为止,使用度非常高,但也最为复杂。

Git Flow

项目存在两个长期分支:

  • master 主分支,稳定代码,为生产环境做准备的
  • develop 开发分支,为开发服务

另外项目存在三种短期分支:

  • 特性分支(feature branch): 从develop分支创建,用于特性开发,完成后要合并回develop分支。

    操作过程:

    1
    2
    3
    4
    5
    git checkout -b newfeature develop,从develop分支创建newfeature特性分支
    git checkout develop,开发完成后,需要合并回develop分支,先切换到develop分支
    git merge --no-ffnewfeature,合并回develop分支,必须加--no-ff参数
    git branch -d newfeature,删除特性分支
    git push origin develop,把合并后的develop分支推送到远程仓库
  • 发布分支(release branch):从develop分支创建,用于预发布版本,允许小bug修复,完成后要合并回develop和master。

    操作过程:

    1
    2
    3
    4
    5
    6
    7
    gitcheckou -b release-1.2 develop,创建一个发布分支 
    git checkout master,切换到master分支,准备合并
    git merge --no-ff release-1.2,把release-1.2分支合并到master分支
    git tag 1.2,从master分支打一个标签
    gitcheckou develop,切换到develop分支,准备合并
    git merge --no-ff release-1.2,把release-1.2分支合并到develop分支
    git branch -d release-1.2,删除这个发布分支
  • 修复分支(hotfix branch):从master分支创建,用于生产环境上的Bug修复,完成后要合并回develop和master。
    操作过程:

    1
    2
    3
    4
    5
    6
    7
    git checkout -b hotfix-1.2.1 master,从master分支创建一个Bug修复分支 
    git checkout master,切换到master分支,准备合并
    git merge --no-ff hotfix-1.2.1,合并到master分支
    git tag 1.2.1,为master分支创建一个标签
    git checkout develop,切换到develop分支,准备合并
    git merge --no-ff hotfix-1.2.1,合并到develop分支
    git branch -d hotfix-1.2.1,删除hotfix-1.2.1分支

优缺点

优点:

  1. 适合于版本周期明确的大型项目
  2. 工作流设计比较完备,包含专门用于生产环境问题修复的渠道

缺点:

  1. 开发容易忘记要从develop拉出feature分支,而是习惯从master拉取
  2. 开发者使用develop分支进行开发,但是默认的发布分支是release分支,开发者需要频繁的切换分支

对于大部分项目来说,工作流程过于复杂

Github Flow

Github Flow
它只有一个长期分支 master ,而且 master 分支上的代码,永远是可发布状态, 一般master 会设置 protected 分支保护,只有有权限的人才能推送代码到 master 分支。

开发流程:

1
2
3
4
5
1. 如果有新功能开发,可以从 master 分支上检出新分支。
2. 在本地分支提交代码,并且保证按时向远程仓库推送。
3. 当你需要反馈或者帮助,或者你想合并分支时,可以发起一个 pull request。
4. 当 review 或者讨论通过后,代码会合并到目标分支。
5. 一旦合并到 master 分支,应该立即发布。

优缺点

优点:

  1. 最大优点就是简单,对于持续发布的产品是最合适的流程

缺点:

  1. 要求master分支的更新与产品的发布是一致的。但有时候代码合并进入master分支,并不代表它就能立刻发布。比如有固定发布窗口期和需要等待审核的产品
  2. 不适合任何生产环境代码落后于master代码的情况

Trunk Based Development

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

优缺点

优点:

  1. 合并冲突少
  2. 利于持续集成,持续交付
  3. 版本迭代速度快

缺点:

  1. 对持续集成、验证要求高
  2. 对团队成熟度要求高
  3. 主干上存在未开发完全的功能

GitLab Flow

这个工作流十分地年轻,是GitLab的 CEO SytseSijbrandij在 2014 年 9月 29 正式发布出来的。因为出现的比前面两种工作流稍微晚一些,所以它有个非常大的优势,集百家之长,补百家之短。

对于”持续发布”的项目,它建议在master分支以外,再建立不同的环境分支。比如,”开发环境”的分支是master,”预发环境”的分支是pre-production,”生产环境”的分支是production。

开发分支是预发分支的”上游”,预发分支又是生产分支的”上游”。代码的变化,必须由”上游”向”下游”发展。比如,生产环境出现了bug,这时就要新建一个功能分支,先把它合并到master,确认没有问题,再cherry-pick到pre-production,这一步也没有问题,才进入production。

只有紧急情况,才允许跳过上游,直接合并到下游分支。
Gitlab Flow
对于”版本发布”的项目,建议的做法是每一个稳定版本,都要从master分支拉出一个分支,比如2-3-stable、2-4-stable等等。

以后,只有修补bug,才允许将代码合并到这些分支,并且此时要更新小版本号
Gitlab Flow

优缺点

优点:

  1. 对于持续部署,持续交付有很好的支持
  2. 解决了测试、预发布、正式上线的不同环境问题
  3. 有明确开发分支和发布分支的规则定义
  4. 支持多版本并行的方式

缺点:

  1. 持续发布的工作流只关心最新版本,对历史版本无记录
  2. 分支与环境的融合

对比

开发、发布分支选择:

  1. TBD 是主干开发,支持分支发布,也支持主干发布。
  2. Git-Flow 是分支开发,分支发布。
  3. GitHub-Flow 是分支开发,主干发布。
  4. GitLab-Flow 是分支开发,支持主干发布,也支持分支发布。

各个策略都有优缺点,合适自己的,才是最好的

Diff
Diff