Git-Flow二三事

769 阅读10分钟

是什么

定义:

GitFlow工作流定义了一个围绕项目发布的严格分支模型,它为不同的分支分配了明确的角色,并定义分支之间何时以及如何进行交互。

翻译一下就是每个分支有个特殊的标识符,用来表示该分支的作用,常用的标识符与它们所代表的意义如下:

  • master:这就不解释了,主分支
  • develop:沙箱分支,也不解释了
  • feature:该分支一般用来表示开发新功能,当开发一个新功能时,可基于master分支创建一个新的feature分支,并且在feature分支上进行开发,开发完成后,合并featrue分支到develop分支上,待测试完成后,合并feature分支到master分支即可。
  • hotfix:该分支主要用于修补master分支上出现的问题,也就是线上突然出问题了。此时需要基于master分支创建hotfix分支,开发完成后直接合并hotfix分支到master分支上,待测试无误时可在develop分支上拉取master分支代码,修补develop分支上的hotfix
  • release:用来发布版本的分支,笔者没用过,在此不多做赘述,有兴趣的老师可自行查阅相关资料。

怎么用(官方)

关于怎么用其实有比较多的争议,先说下官方给的用法:

PS:各颜色代表的分支为:

  • 绿色代表master分支
  • 紫色代表hotfix分支
  • 黄色代表release分支
  • 橙色代表develop分支
  • 蓝色代表feature分支

以一次完成的:新需求开发->测试->上线->回归->线上BUG->修复->上线->验证为例子。

  1. 创建develop分支

    在开始开发之前,首先从master分支上剥离出develop分支

    image.png

    这一步就不详细介绍了,节省时间。

  2. 创建feature分支

    image.png

    注意,官方给的建议是此时的feature分支应基于develop分支,然后就是普通的开发流程~

  3. 准备第一次发布(沙箱)

    image.png

    image.png

    发布可以简单理解为上沙箱。也就是先把feature分支合并到develop分支上,基于develop分支创建release分支,最后利用release分支上到沙箱

  4. 上线

    image.png

    上线这就很简单了,把release分支分别合并到masterdevelop分支上即可,之后在master分支上上线即可

  5. 线上BUG

    image.png

    虽然很不希望看见这种情况,但它有时候还是会出现,那么此时需要基于master分支创建一个hotfix分支,基于hotfix分支进行线上BUG修复,修复完成后合并到master分支上再次上线,测试没问题就完事了。

最后总览一下整个流程:

gitflow-info-5.png

PS:需要注意的是,官方推荐每次使用完一个分支(除外masterdevelop分支)后需要将该分支完成并删除

怎么用(曾经)

好了,说一下笔者曾经的用法,这一点每个公司都有着自己的标准,此处只提供一种思路。

首先,和官方文档上最大的不同就是feature分支是基于master分支而不是develop分支。

先捋一下流程:

  1. 创建develop分支

    这一步和官方文档一样,不多做赘述。

  2. 创建feature分支

    基于master分支创建feature分支,进行开发

  3. 上沙箱

    develop分支上拉去feature分支,注意,此处并非合并,而是拉取。

    之后将develop分支上到沙箱,供测试老师进行操作

  4. 上线

    这一步和官方一样,直接将feature分支合并到master分支即可。

  5. 线上BUG

    基于master分支创建hotfix分支,并在该分支上进行开发,开发完成后合并到master分支即可。

OK,现在说一下为什么feature分支要基于master分支,其实一开始笔者的feature分支也是基于develop分支的。

首先由于大环境问题,之前笔者的沙箱是基于develop分支的,如果需要上某些东西到沙箱,需要将该分支合并到develop分支上。

那么在feature分支基于develop分支的情况下,合并featuredevelop看上去很合理也很简单,但是如果多个feature分支同时存在,并且相互之间有一定关系则会出现一些问题。

比方说develop分支上已经有了feature/f1分支,此时新新建feature/f2分支则会包含feature/f1分支,那么如果要上到master分支,f2必须在f1之后,否则会出现一些问题。

但事实上这样做极有可能会影响测试老师的排期, 并且如果f1分支delay了,f2分支也会受到影响,这是我们不愿意看到的。

feature分支基于master分支则可完美的解决这个问题,不论如何f1都不会影响到f2

上沙箱只需要在develop分支上拉取feature分支即可,无需merge,直接将拉取后的develop推上去即可(有CI工具更佳,没有CI工具手动上线亦可)。

测试完成后,可以提一个merge,进行code revivew后即可合并分支,上线回归~

如果线上有问题,创建hotfix分支即可,和官方推荐用法并无差别。

配置

安装就不说了,具体可参考这篇文档

PS:Mac不用管,Windows需要安装cynwin工具

安装完Git Flow之后,在需要使用的项目路径下执行以下代码:

image.png

需要注意的是在初始化选择分支的时候,将发布分支选为develop,之后将next release分支改为master,否则git flow feature ...的分支会是基于develop而不是master分支

之后如果需要新建开发分支,可执行一下代码:

git flow feature start f1

之后会自动切换分支到f1上,直接开发即可。hotfix分支同理。

对于官方说的在需求完成后关闭并删除分支的做法,确实比较麻烦,如无必要,可以不做此步操作。

其他

commitizen

说道Git Flow,还有一个工具也是很方便的——commitizen。

该工具可以使得我们的commit信息更加完善和具体,并且有着统一的格式。

同上,安装过程就不说了,windows环境尝试多次无果,遂放弃,Mac直接使用即可。

为保持统一的格式,windows环境下可以手动更改commit信息来达到同样的效果。

使用方法也很简单,无需git add .git commit -m ''了,直接在项目根目录下执行git cz,需要注意的是:如果是新建文件,可能仍然需要手动git add .,否则可能会出现添加不上的情况。

执行完git cz之后,命令行会是这个样子的:

image.png

这里可以选择此次提交的类型,分别是:

  • feat: 新的功能点
  • fix:BUG修复用
  • docs:仅更改文档
  • style:并非仅仅针对于修改,对该类型的定义应该是:不影响代码意义的修改
  • refactor:用来代表一些不是修复BUG也不是增加新功能的提交
  • perf:用来提升性能表现
  • test:测试用例啥的

大概齐就这些了,选择了某一类型之后,在commit信息中会自动包含这些信息。

之后回车,页面会出现一些问题让你回答:

image.png

可以根据这些问题来进行回答,都完成后可以得到一个完整的有着标准格式的commit:

![image-20200910205350807](/Users/zhenghanjing/Library/Application Support/typora-user-images/image-20200910205350807.png)

在GitLab上的展示也会一目了然,非常方便。(上面的commit信息有点问题是因为和之前分支有冲突,所以额外信息放到了解决冲突的commit下)

当然了,在使用GitFlow的同时依然可以使用传统的git commit来进行提交,为了强制统一commit的格式可以使用validate-commit-msg+husky来在提交时进行校验,如果不通过则会报错,无法成功提交,这一点在项目中已有实践,不多做赘述。

Github Flow

说一些题外话,可能大家都知道GitFlow,没用过也应该听说过,但这其实并不是Git官方推荐,虽然它叫GitFlow。

那么Github官方推荐是什么呢?那就是Github Flow(后续简称GHF,Git Flow简称为GF)。

那么GHF是什么呢?其实它跟GF是两种完全不同的操作方式,它主要使用的是Pull Request。

相信在GitHub上有过开源项目贡献的老师应该都知道,它的主要流程如下:

  1. 首先Fork一个仓库到本地
  2. 在本地对代码进行修改,(分支无所谓,新建分支或者直接在master分支上修改都可以)
  3. 之后回到原来的项目,进行Compare & Pull Request操作,添加注释并且提交
  4. 源项目的作者就会收到merge的请求

使用GHF也是同样的逻辑,不过在GitLab中好像没有Pull Request的操作,此处了解下即可。

不该用Git Flow?

GF到现在也有10年的时间了,最开始是在2010年由Vincent Driessen和他所在的组织采用并总结出的一套工作流程,在此期间有很多人对它提出的意义,总结一下主要有以下几点:

  • 过于复杂

    这一点确实是,从第二节(官方推荐用法)可以看出来其整体流程相较于普通的工作流程来说复杂了很多,同上面的GHF来说更是复杂了很多倍

    由于分支种类繁多,分支追踪会更加困难

  • 违反了「短命」分支规则

    分支存在的周期过长,并且由于多个分支交叉,出现冲突的可能性骤增,对于需要频繁更新的项目很不友好

  • 没法用rebase

    重新定位合并节点是一个复杂的话题。如果你使用GF,不得不放弃rebase。因为rebase 取消了合并提交,你再也看不到两个分支组合在一起的节点。由于GF的视觉复杂性,你需要可视化地跟踪分支,这意味着如果想解决问题,就不能rebase

  • 连续交付十分困难

    由于整体流程比较复杂,如果需要频繁更新代码,使用GF显然不是一个好的选择

还有其他弊端,但与工作联系不大,这里不多做赘述,有兴趣的老师可以点击这里

小结

本次分享主要介绍了GF的主要用法,并且以笔者的经历举个栗子,其实可以看出,这其实是个简化版的GF。

后续介绍了一些其他的内容,比方说方便规范commit格式的commitizen和另外一种Git工作流——GHF。

关于GF最后的结论可能是这样的:

如果团队中人数较多(20人+),并且项目更新周期不长(15天+) ,那是GF是一个比较好的选择。

如果人数较少或者项目周期比较频繁,那么GF可能并不是一个好的选择,可能会花费很多的时间在整理Git工作流上,此时可以使用简化版本的GF或者使用其他合适的工作流。