路漫漫其修远兮
吾将上下而求索

git学习:Git Flow

Git Flow

说到 Git 分支管理,一个绕不开的东西就是 Git Flow 了。这是一个 2010 年被提出的"古典"分支模型,历经了近 10 年,依然被广泛使用。

首先,它对分支按照功能分为几类:

  • master:主干分支:包含最新的稳定代码,应该时刻保持可以被部署上线的状态。

  • develop:研发分支:从项目启动后,立即从 master checkout 得到。包含最新开发完毕的 feature,可能存在问题,不能保证随时上线部署

  • release:发布分支:当某个迭代周期中的 feature 均开发完毕后,从 develop checkout 得到,仅包含当前 release 的后续 bug 修复代码。在 release 正式发布,合并到 master 后,即可进行删除。

  • feature/*:开发独立特性分支:无法保证能稳定运行。在需求确认开始研发时,从 develop checkout 得到,相对 master 和 develop 这两个 long-lived 分支,feature 分支通常在开发完毕被合并到 develop 后,即可进行删除。

  • hotfix/*:bug修复分支:通常是在已发布版本上发现了严重 bug,必须立刻修复时,从 master checkout 得到。在修复完毕后,需要同时合并到 master 和 develop。

如果感觉文字描述的不够清晰的话,可以参考下图。 

下面我们来分析下,这个初看非常复杂的模型中,各个分支存在的必要性。

20210119-4863516591.png

master

不管用什么分支模型,甚至不管什么版本控制软件,master 的定位都几乎相同,这里就不展开说了

develop

假如没有 develop 分支,我们会面临什么情况。

我们最新提交的代码,唯一的选择是在完整测试后,在预期上线时间前,合并到 master 分支。

这样会带来一个很大的限制:需求和代码质量必须严格可控。如果一个需求今天计划下周发布,而在下周出现了不可预计的问题导致必须延期,那么工程师如何选择合并到 master 的时间节点?

当然,我们可以选择在上线前一天进行合并,但是我们需要考虑一个问题,代码并不是合并到 master 就能直接上线的. 我们需要在上线前做充分的集成测试,而 master 分支是在不停演化的,本周 feature 合并到 master 可以通过测试,可能下周其他工程师会提交一段代码,导致你的 feature 无法正常工作。于是我们的特性分支要频繁的 merge master,并修复因此导致的问题 。

这样反复集成带来的时间成本是非常高的,负责开发特性的工程师,排期要一直被占用,即使代码已经开发完毕。这也是为什么通常大型软件项目会分配专人做源码管理,甚至安排 release manager 了。

而有了 develop 分支后,由于我们的特性分支不会污染 master。在功能开发完毕后,我们可以放心的合并到 develop, 并在 release 分支开出后, 统一安排解决集成导致的问题.

release

release 分支要解决的问题, 其实和 develop 类似:

当我们某个版本的功能全部开发完毕后, 如何保证下个版本新签入的代码不会影响本次要发布的功能?

毕竟, 我们不能让工程师都停下来等待这次发布完成

不足

经过简单的分析, 我们可以看到 gitfow 意在提出一个充分灵活, 并且稳定的分支模型, 尽可能的提升工程研发效率。那么它是不是完美的呢?

任何设计, 都有其背景, gitflow 提出的时间相对较老, 更加适合传统一些的软件项目, 迭代周期可能是月甚至是季度, 需求也相对稳定

而在互联网公司, 动辄以天计算的迭代中, 有些力不从心:

feature 分支如果不能快速合并到 develop, develop 上快速的迭代, 会导致 feature 分支失效, 甚至可能在真正需要上线时重写

release 分支存在的价值减弱, feature 在开发完毕后, 可能在一周内快速部署上线, 合并到 master, 那么维护一个 release 分支的成本甚至比它带来的收益要高. 所以有些时候, 我们会放弃 release 分支, 让 master 承担其责任, 在上线时合并到 master, 进行部署, 但这引出了下面的问题

如果一个特性合并到 develop 后发现不能立即上线, 则会阻塞后续特性的迭代。一种选择是,隔离 develop master,上线时采用 cherry-pick 需要的特性到 master 进行上线。但这样会导致 develop 和 master 的分歧越来越大。那么 develop 和 master 究竟谁才是“主干”呢

Trunk based development

在遇到了以上问题后, 近几年一个"老模型"又焕发了活力. 

非常简单清晰的模型。只有两种分支:master 和 release。

所有提交均在 master 上进行。在某个 release 特性开发完毕后,分出一个 release 分支。

如果发现 release 上有 bug 需要进行修复,则在 master 上进行修复,然后 cherry-pick 到 release 分支。

这个模型在 git 普及起来之前,工程师普遍使用 svn 的年代,非常流行。

由于 svn 对分支非常不友好,所以我们的选择就是不开分支,统一向 trunk ( svn 中的 master )提交。

对于迭代相对快的公司,甚至连 release 分支都可以省掉: 直接从 master 上线, 出现问题就在 master 修复, 并立即上线修复.

这种方式,解决了特性分支无法快速合并到主干的尴尬:特性分支必须是小的变更,在几天内即可完成,完成即合并到 master。

那么如何保证 master 的稳定可随时部署的问题呢?答案是用特性开关或者 ab 测试的方式,

所有新开发完毕的特性, 均使用特性开关进行保护, 这样即使发布计划外的特性也可以安全的部署上线.

这种方式非常适合高速迭代的互联网公司, 可以支撑每天多次的上线部署. 代价就是牺牲了服务质量:

  1. 特性开关也不是 100% 安全的

  2. cherry-pick 还是存在一定的维护成本, 并且丢失了 release 完整的上下文, 无法一目了然的获取一次 release 具体会上线哪些特性

毕竟效率和质量很难兼得. 但互联网公司吗, 都是众包测试 :), 无所谓了.

未经允许不得转载:江哥架构师笔记 » git学习:Git Flow

分享到:更多 ()

评论 抢沙发

评论前必须登录!