Gitflow 使用最强指北

2019年11月17日 阅读数:25
这篇文章主要向大家介绍Gitflow 使用最强指北,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

代码管理是整个项目管理周期中重要的一环,而代码管理是始终围绕版本发布流程而制定的,今天讨论的Gitflow就是一种版本发布方案。html

Gitflow简介

Gitflow是一个基于feature分支管理的版本发布方案。它是由荷兰程序猿Vincent Driessen设计研发,开源项目地址gitflow-avhgit

大体流程是:github

  • 不一样feature在不一样feature分支上单独开发(或测试)。
  • 肯定版本号和此版本将要发布的功能后,将相应featustre分支统一贯develop分支合并,而后拉出新的release预发布分支。
  • release分支做为持续集成关注的分支,修复bug。
  • 待release分支测试验收经过后,统一贯master分支和develop分支合并,并在master分支打tag。
  • 根据tag发布apk版本。

若线上发现严重bug,需走hotfix流程。bash

  • 基于master分支拉出hotfix分支修复线上问题。
  • bug修复完成统一贯master和develop分支合并。
  • master分支打上新的tag,发布新版本。

下图是Gitflow发布的经典图片,直观反映了Gitflow发布的全流程。ide

gitflow.png

它的特色是能灵活的根据实际需求发布相应版本,较好的支持并行开发,历史版本用tag进行维护。工具

下面将介绍如何使用Gitflow命令完成上述版本发布,一条Gitflow指令可能对应了一系列git命令,为的是规范化开发流程,提升代码管理效率。gitlab

Mac平台安装

brew install git-flow
复制代码

brew表示Homebrew,它是mac平台经常使用的包管理器,没有安装则需先安装,安装可参考Mac OS下brew的安装和使用测试

初始化

先将远程仓库克隆到本地。fetch

git clone <project_url>
复制代码

各类初始化Gitflow配置。ui

git flow init
复制代码

命令行会提示你是否修改Gitflow提供的默认分支前缀。不一样场景的分支前缀不一样,默认状况下分支前缀是这样的:

场景 分支前缀
新功能 feature
预发布 release
热修复 hotfix
打tag

分支前缀的做用是区分不一样分支的使用场景,同时当你使用Gitflow命令时就不需手动添加分支前缀了,Gitflow会帮你加上。

好比开发新功能需建立一个feature分支,名为gitworkflow,使用下面的代码将会建立一个名为feature/gitworkflow本地分支。

git flow feature start gitworkflow
复制代码

一般状况下不须要修改默认的命名前缀,只需加上-d就可跳过修改命名阶段。

git flow init -d
复制代码

行为/Action

一般来讲,一种场景的完整生命周期应至少包含如下几种行为:

  • start 开始开发
  • publish 发布到远程分支
  • finish 完成开发、合并到主分支

咱们首先以feature场景为例,看看如何完成工做流。

start

新功能开始开发前,需准备好开发分支。

git flow feature start <feature_name>
复制代码

执行上面的命令将会在本地建立名为<feature_name>的分支,并切换到该分支,并且不论当前所处哪一个分支都是基于develop分支建立,至关于执行了下面的git的命令。

git checkout -b feature/<feature_name> develop
复制代码

须要注意基于的是本地的develop分支,执行此命令前通常须要拉取最新的远程代码。

publish

在本地开发完成新功能并commit后,须要将本地代码push到远程仓库。

git flow feature publish <feature_name>
复制代码

这行指令作了三件事。

  1. 建立一个名为feature/<feature_name>的远程分支。
  2. 本地分支track上述远程分支。
  3. 若是本地有未push代码,则执行push。

转换成git命令就是下面的样子:

git push origin feature/<feature_name>
git push --set-upstream origin feature/<feature_name>
git push origin
复制代码

注意:

若是已经执行过publish后又有新的代码需push,再次执行将报错,由于它始终会试图建立一个远程分支。此时需执行正常的push命令git push origin

finish

当功能开发完毕后就将进入测试阶段,此时需将一个或多个feature分支统一合并到develop分支。

git flow feature finish <feature_name>
复制代码

这行指令也作了三件事。

  1. 切换到develop分支。
  2. 合并代码到develop分支
  3. 删除本地feature/<feature_name>分支。

等价于执行下面的git命令:

git checkout develop
git merge feature/<feature_name>
git branch -d feature/<feature_name>
复制代码

说到merge,就不得不提merge采用的策略,咱们使用git merge命令时默认(主分支没有新的提交、没有冲突等状况)使用的是fast-forward模式(如下简称ff),即只移动HEAD指针而不会生成提交记录。

而Gitflow稍有不一样,默认状况下它会检查本次merge有多少次commit记录,若是仅有一条采用ff模式,若是超过一条则采用no-ff模式,no-ff模式下会多生成一条merge的commit记录。

这样作的好处是当只有一条提交记录时若是生成一条merge记录实际上会复杂化代码记录的管理;当有多条commit记录时生成的一个merge记录,能够方便的进行代码回退和记录检查。

回到finish主题,若是merge时发生了冲突,则在第二步merge时终止流程,即不会再删除本地分支。但当前已处于develop分支,待本地冲突解决并commit后,从新执行git flow feature finish <feature_name>便可完成finish流程。

细心的同窗能够已经发现finish还有两件事没作。

  1. develop分支代码还未push。
  2. 未删除远程分支feature/<feature_name>。

也就是还需执行

git push origin develop
git push origin :feature/<feature_name>
复制代码

另外,finish指令支持三个附加参数。

  • -r 即merge前先执行rebase(但即便rebase后符合ff条件也不必定会用ff)。
  • -F 即合并完成后连同远程分支一并删除。
  • -k 保留本地feature分支,即不执行delete动做。

因此若是想连同远程分支一并删除可以使用。

git flow feature finish -F <feature_name>
复制代码

若是你对feature指令感兴趣,下面是其支持的全部指令。

git flow feature [list] [-v]
git flow feature start [-F] <name> [<base>]
git flow feature finish [-rFk] <name|nameprefix>
git flow feature publish <name>
git flow feature track <name>
git flow feature diff [<name|nameprefix>]
git flow feature rebase [-i] [<name|nameprefix>]
git flow feature checkout [<name|nameprefix>]
git flow feature pull <remote> [<name>]
复制代码

release场景

上面的内容以feature场景为例,详细的分析了整个新功能执行流程。

下面咱们再来看release场景,连同以前的feature场景,整个流程以下。

release.jpg

当新功能开发完毕,将进入测试阶段,此时须要基于develop分支拉出release分支进行集成测试,也有将release场景做为预发布环境进行测试的,即feature场景已完成常规测试,在这种状况下,通常而言release只有少数改动。在这里咱们先不讨论项目流程问题。

使用start指令开启一个release场景,一般以版本号命令,咱们以v2.0为例:

git flow release start v2.0
复制代码

此命令会基于本地的develop分支建立一个release/v2.0分支,并切换到这个分支上。

为了让其余协同人员也能看到此分支,须要将其发布出去。

git flow release publish v2.0
复制代码

以上和feature场景十分相似。

待测试经过须要发布正式版:

git flow release finish v2.0
复制代码

这一步作的动做有点多,大体是:

  1. git fetch
  2. release/v2.0分支代码向master合并。
  3. 生成名为v2.0的tag。
  4. release/v2.0分支代码向develop合并。
  5. 删除本地release/v2.0分支。
  6. 切换回develop分支。

若是merge产生冲突不会终止流程,只是不会将本地的release分支删除,待解决完冲突后需再次执行finish指令。

另外须要注意的是,若是本地还有未finish的release分支,将不容许使用start指令开启新的release分支,这一点是对并行发布的一个限制。

release finish只是完成了本地代码的一系列操做,还须要同步到远程仓库。

git push origin develop
git push origin master
git push origin v2.0
复制代码

或者使用下面的命令推送全部的分支和tag。

git push origin --all
git push origin --tags
复制代码

hotfix场景

当tag打完,也表示正式版本发布出去了,若是此时在线上发现了严重的bug,须要进行紧急修复,流程以下:

hotfix.jpg

此时咱们假设版本号变为v2.0-patch。

git flow hotfix start v2.0-patch
复制代码

这将建立一个hotfix/v2.0本地分支并切换到该分支。 hotfix没有publish指令,认为hotfix应该是个小范围改动,不须要其余协同人员参与。

待本地修改结束commit后,执行finish指令。

git flow hotfix finish v2.0-patch
复制代码

按照Gitflow工做流,它会执行下面的任务,与release基本一致。

  1. git fetch
  2. hotfix/v2.0-patch分支代码向master合并。
  3. 生成名为v2.0-patch的tag。
  4. hotfix/v2.0-patch分支代码向develop合并。
  5. 删除本地hotfix/v2.0-patch分支。
  6. 切换回develop分支。

快捷脚本

在实际开发中发现,Gitflow命令有点长,容易敲错。好比git flow feature start <name>,所以我写了一个简化的指令,经过它能够这样写./gitflow -fs <name>。也就是取Gitflow指令关键字的首字母组合,为新的指令集。

详情参见Github gitflow.sh

Sourcetree支持

Sourcetree彻底支持Gitflow的全部操做,若是你习惯于使用图形化工具管理你的代码,能够直接使用Sourcetree的Gitflow功能。

Sourcetree操做界面.png

了解了上面的命令,这个图形化界面基本就都能见名知意了。

其余代码工做流

与Gitflow类似的代码管理工做流还有,Github flow和Gitlab flow。

Github flow是简化版的Gitflow,它使用master和feature来管理代码,它只有一个长期分支,就是master。Gitlab flow更关注代码的持续集成,一个版本须要建立测试环境、预览环境、生产环境的分支,最终汇总到stable branch用于发布,感兴趣的小伙伴能够自行了解。

下表是笔者对三者特色的理解:

项目 Gitflow Github flow Gitlab flow
特色 基于master和develop分支 基于master分支和PR 基于master分支,使用“上游优先”原则
易用性 复杂,需结合Gitflow工具 简单 通常
并行开发 简单 通常
侧重点 灵活性、多feature管理/版本管理 分支维护效率 持续集成
历史版本维护 tag tag或stable branch stable branch

实际上Gitflow的发布流程一直饱受争议,反对者认为feature开发周期通常较长,也就是可能在较长时间内不能合并到主干分支,这不利于持续集成,且在合并到主干时可能产生大量冲突,参看这篇Gitflow有害论

但笔者认为若是你正在参与一个企业级的项目,一个版本将要上线的features可能因各类缘由变更或下线,此时若是没有独立的feature分支而所有在主干分支,将极难处理代码的回滚和保护;换个角度说,merge冲突也能够经过其余方式规避,好比良好的代码分层、事先约定好跨模块通讯的接口等。

从持续集成的角度来讲,因为Gitflow管理的分支类型较多,不该全部分支都参与持续集成,可结合实际场景选择开启持续集成的分支类型,好比master和release。

最后,没有最好的方案,只有最适合的方案,实际的项目管理过程当中应根据不一样工做流的特色选择适合的方案便可。

若是你还有什么疑问,欢迎留言探讨。