引言
GitLab作为一站式DevOps平台,其首先最基础的功能必然是源代码版本管理。而其源代码管理是基于Git,Git通过支持分支独立安全地处理功能和错误修复,实现安全、可靠和快速的分布式软件开发工作流。Git作为一个源代码版本管理工具,其允许多种分支策略和工作流程。但很多组织在使用过程中,由于采用了不合理的分支策略导致工作流过于复杂,使得版本管理混乱。为了规范Git流程,业界提出了第一个Git分支提案:Git flow,接下来就先来介绍下Git flow,以便更好的理解Gitlab flow。
Git flow
Git flow作为一种分支策略标准,其分支策略如下图所示,从图中可以看出其主要有六大分支,其流程是:
首先从
main
分支创建develop
分支用于开发,main
分支不允许push
,只允许合并然后基于
develop
分支创建feature
分支进行特性开发,特性开发完毕后合并到develop
分支也可基于
develop
分支创建bugfix
分支进行bug修复,bug修复完毕后合并到develop
分支在
develop
分支验证无误后,再从develop
分支合并到release
分支,同样release
分支不允许push
,只允许合并在
release
分支进行预生产环境验证无误后,将release
分支合并到main
分支,并创建Tag
标识版本号如果在生产环境发现问题需要热修复,则基于
main
分支创建hotfix
分支,修复验证通过后,直接从hotfix
分支合并到main
分支,并通过Tag
创建新版本号。其中
main
、release
分支是不允许修改的。
在实际项目中如何应用Git flow呢?可以通过git flow
命令行进行应用,对于Windows系统只要安装git
后即可直接使用,其他系统需要自行安装git-flow
插件。安装成功后即可在git bash
中执行git flow
,可以看到包含以下命令:
$ git flow
usage: git flow <subcommand>
Available subcommands are:
init Initialize a new git repo with support for the branching model.
feature Manage your feature branches.
bugfix Manage your bugfix branches.
release Manage your release branches.
hotfix Manage your hotfix branches.
support Manage your support branches.
version Shows version information.
config Manage your git-flow configuration.
log Show log deviating from base branch.
Try 'git flow <subcommand> help' for details.
接下来就在本地创建一个GitFlow.Demo
项目,来讲解下git flow
的应用流程。
初始化仓库
首先了解下如何使用git flow
初始化一个支持分支模型的git仓库,参照以下步骤即可完成:
shengjie@Thinkpad MINGW64 /d/Gitlab/Demos
$ mkdir GitFlow.Demo # 创建项目目录
shengjie@Thinkpad MINGW64 /d/Gitlab/Demos
$ cd GitFlow.Demo/ # 进入目录
shengjie@Thinkpad MINGW64 /d/Gitlab/Demos/GitFlow.Demo
$ git flow init # 初始化一个支持分支模型的git代码仓库
Initialized empty Git repository in D:/Gitlab/Demos/GitFlow.Demo/.git/
No branches exist yet. Base branches must be created now.
Branch name for production releases: [master] main # 命名生产分支,将master更名为main
Branch name for "next release" development: [develop] # 以develop命名开发分支,直接回车即可
How to name your supporting branch prefixes?
Feature branches? [feature/] # 以feature命名特性分支,直接回车
Bugfix branches? [bugfix/] # 以bugfix命名bug修复分支,直接回车
Release branches? [release/] # 以release命名发布分支,直接回车
Hotfix branches? [hotfix/] # 以hotfix命名热修复分支,直接回车
Support branches? [support/] # 以support命名支持分支,直接回车
Version tag prefix? [] # 指定版本标识前缀,直接回车
Hooks and filters directory? [D:/Gitlab/Demos/GitFlow.Demo/.git/hooks]
shengjie@Thinkpad MINGW64 /d/Gitlab/Demos/GitFlow.Demo (develop) # 初始化成功后,会自动切换到develop分支
$ git branch # 查看初始化的分支
* develop
main
$ git flow config # 查看当前git flow 配置
Branch name for production releases: main
Branch name for "next release" development: develop
Feature branch prefix: feature/
Bugfix branch prefix: bugfix/
Release branch prefix: release/
Hotfix branch prefix: hotfix/
Support branch prefix: support/
Version tag prefix:
初始化成功后,将本地代码库映射到远程仓库,直接使用上一节创建的GitFlow.Demo
项目作为远程仓库,在项目页找到克隆地址,然后执行git remote add origin [https://gitlab.shengjie.dev/demos/gitflow.demo.git](https://gitlab.shengjie.dev/demos/gitflow.demo.git)
(注意,这里要替换为自己的仓库地址)完成远程仓库映射,最后再执行git push -u --all
将本地分支推送到远程。
操作feature分支
接下来演示下如何使用feature分支进行特性开发,主要使用git flow feature
命令进行操作:
$ git flow feature help # 查看 git flow feature 命令
usage: git flow feature [list] # 查看本地feature 列表
or: git flow feature start # 开启一个新的feature
or: git flow feature finish # 完成一个新的feature,会自动删除feature分支,并合并到develop分支
or: git flow feature publish # 如果需要code review,可以执行该命令将feature分支推送到远程仓库
or: git flow feature track
or: git flow feature diff
or: git flow feature rebase
or: git flow feature checkout
or: git flow feature pull
or: git flow feature delete
shengjie@Thinkpad MINGW64 /d/Gitlab/Demos/GitFlow.Demo (develop)
$ git flow feature start feature1 # 创建feature1 特性分支
//...
Summary of actions:
- A new branch 'feature/feature1' was created, based on 'develop'
- You are now on branch 'feature/feature1'
Now, start committing on your feature. When done, use:
git flow feature finish feature1
shengjie@Thinkpad MINGW64 /d/Gitlab/Demos/GitFlow.Demo (feature/feature1)
$ touch readme.txt # 创建文件
shengjie@Thinkpad MINGW64 /d/Gitlab/Demos/GitFlow.Demo (feature/feature1)
$ git add .; git commit -m 'Add readme' # 提交文件
shengjie@Thinkpad MINGW64 /d/Gitlab/Demos/GitFlow.Demo (feature/feature1)
$ git flow feature finish # 完成feature开发
//...
Summary of actions:
- The feature branch 'feature/feature1' was merged into 'develop' # feature1 分支被合并到develop分支
- Feature branch 'feature/feature1' has been locally deleted # feature/feature1 分支已经被删除
- You are now on branch 'develop' # 当前分支切换到develop分支
shengjie@Thinkpad MINGW64 /d/Gitlab/Demos/GitFlow.Demo (develop)
$ git push --set-upstream origin develop # 推送到远程develop分支
操作release分支
如果基于最新develop
分支本地环境自测验证无误后,就可以进行提测,主要是将develop
分支合并至release
分支,触发GitLab CI/CD
,自动构建并发布至测试环境,进行发布主要使用git flow release
命令进行操作:
shengjie@Thinkpad MINGW64 /d/Gitlab/Demos/GitFlow.Demo (develop)
$ git flow release help # 查看git flow release 命令
usage: git flow release [list]
or: git flow release start # 开启一个新的release
or: git flow release finish # 完成release
or: git flow release publish # 发布release至远程仓库,进行
or: git flow release track
or: git flow release delete
shengjie@Thinkpad MINGW64 /d/Gitlab/Demos/GitFlow.Demo (develop)
$ git flow release start v1.0 # 创建 v1.0 release发布分支
//...
Summary of actions:
- A new branch 'release/v1.0' was created, based on 'develop'
- You are now on branch 'release/v1.0'
Follow-up actions:
- Bump the version number now!
- Start committing last-minute fixes in preparing your release
- When done, run: git flow release finish 'v1.0'
创建release
分支后,一般会使用git flow release publish
命令将其推送到远程仓库,触发GitLab CI/CD
流水线,将该release
分支发布到测试环境。
shengjie@Thinkpad MINGW64 /d/Gitlab/Demos/GitFlow.Demo (release/v1.0)
$ git flow release publish # 推送至远程分支
//...
Summary of actions:
- The remote branch 'release/v1.0' was created or updated
- The local branch 'release/v1.0' was configured to track the remote branch
- You are now on branch 'release/v1.0'
shengjie@Thinkpad MINGW64 /d/Gitlab/Demos/GitFlow.Demo (release/v1.0)
在测试环境进行验证无误后,才可以使用git flow release finish
命令将此次release
标记完成,进而合并到main
分支,演示如下:
$ git flow release finish v1.0 # 完成v1.0 release
//...
Summary of actions:
- Release branch 'release/v1.0' has been merged into 'main' # 合并release1到main分支
- The release was tagged 'v1.0' # 打标签为v1.0
- Release tag 'v1.0' has been back-merged into 'develop' # 将v1.0合并到develop分支
- Release branch 'release/v1.0' has been locally deleted; it has been remotely deleted from 'origin' # 将release/v1.0 从本地和远程删除
- You are now on branch 'develop' # 切换至develop分支
shengjie@Thinkpad MINGW64 /d/Gitlab/Demos/GitFlow.Demo (develop)
$ git checkout main # 切换到主分支
Switched to branch 'main'
shengjie@Thinkpad MINGW64 /d/Gitlab/Demos/GitFlow.Demo (main)
$ git push --set-upstream origin main # 推送到远程分支
操作bugfix分支
如果测试人员在release
分支对应的测试环境进行验证时发现了一个问题:创建的readme.txt
未添加任何描述。开发人员就可以通过bugfix
分支解决,主要使用git flow bugfix
命令:
$ git flow bugfix help
usage: git flow bugfix [list]
or: git flow bugfix start # 创建bugfix分支
or: git flow bugfix finish # 完成bugfix分支
or: git flow bugfix publish # 如果需要code review, 可以执行该命令将bugfix分支推送到远程仓库
or: git flow bugfix track
or: git flow bugfix diff
or: git flow bugfix rebase
or: git flow bugfix checkout
or: git flow bugfix pull
or: git flow bugfix delete
shengjie@Thinkpad MINGW64 /d/Gitlab/Demos/GitFlow.Demo (release/v1.0)
$ git flow bugfix start bug1 # 开启bug1分支
//...
Summary of actions:
- A new branch 'bugfix/bug1' was created, based on 'develop' # 可以看出是基于develop分支创建的bug1分支
- You are now on branch 'bugfix/bug1'
Now, start committing on your bugfix. When done, use: git flow bugfix finish bug1
shengjie@Thinkpad MINGW64 /d/Gitlab/Demos/GitFlow.Demo (bugfix/bug1)
$ echo 'Hello git flow!' > readme.txt # 修改readme
shengjie@Thinkpad MINGW64 /d/Gitlab/Demos/GitFlow.Demo (bugfix/bug1)
$ git commit -am 'Update readme' # 提交readme
shengjie@Thinkpad MINGW64 /d/Gitlab/Demos/GitFlow.Demo (bugfix/bug1)
$ git flow bugfix finish bug1 # 完成bug1修改
//...
Summary of actions:
- The bugfix branch 'bugfix/bug1' was merged into 'develop' # 合并到develop分支
- bugfix branch 'bugfix/bug1' has been locally deleted # 删除bug1 分支
- You are now on branch 'develop' # 切换至develop分支
shengjie@Thinkpad MINGW64 /d/Gitlab/Demos/GitFlow.Demo (develop)
$ git push # 再次推送到远程develop分支
完成问题修复后,可再从develop
分支进行发布release
。
操作hotfix分支
在release分支合并到main分支后,就可以进行生产环境发布了。基于main分支发布到生产环境后,如果发现紧急问题,则可以通过hotfix
分支进行热修复。热修复流程注意使用git flow hotfix
命令操作,演示如下:
shengjie@Thinkpad MINGW64 /d/Gitlab/Demos/GitFlow.Demo (develop)
$ git flow hotfix help
usage: git flow hotfix [list]
or: git flow hotfix start # 启动热修复
or: git flow hotfix finish # 完成热修复
or: git flow hotfix publish # 推送热修复至远程分支
or: git flow hotfix delete
shengjie@Thinkpad MINGW64 /d/Gitlab/Demos/GitFlow.Demo (develop)
$ git flow hotfix start hotfix1
//...
Summary of actions:
- A new branch 'hotfix/hotfix1' was created, based on 'main' # hotfix 分支是基于main分支创建的
- You are now on branch 'hotfix/hotfix1'
Follow-up actions:
- Start committing your hot fixes
- Bump the version number now!
- When done, run: git flow hotfix finish 'hotfix1'
shengjie@Thinkpad MINGW64 /d/Gitlab/Demos/GitFlow.Demo (hotfix/hotfix1)
$ sed -i 's/git flow/GitFlow/#' readme.txt # 假设是需要将readme.txt中的git flow 替换为GitFlow
shengjie@Thinkpad MINGW64 /d/Gitlab/Demos/GitFlow.Demo (hotfix/hotfix1)
$ git commit -am 'Fix hotfix1: update git flow to GitFlow' # 提交更改
shengjie@Thinkpad MINGW64 /d/Gitlab/Demos/GitFlow.Demo (hotfix/hotfix1)
$ git flow hotfix publish # 推送到远程分支,以便发布验证
//...
Summary of actions:
- The remote branch 'hotfix/hotfix1' was created or updated
- The local branch 'hotfix/hotfix1' was configured to track the remote branch
- You are now on branch 'hotfix/hotfix1'
shengjie@Thinkpad MINGW64 /d/Gitlab/Demos/GitFlow.Demo (hotfix/hotfix1)
$ git flow hotfix finish # 将此次hotfix标记完成
//...
Summary of actions:
- Hotfix branch 'hotfix/hotfix1' has been merged into 'main' # 合并到main分支
- The hotfix was tagged 'hotfix1' # 打标签
- Hotfix tag 'hotfix1' has been back-merged into 'develop' # 合并到develop分支
- Hotfix branch 'hotfix/hotfix1' has been locally deleted; it has been remotely deleted from 'origin' # 删除本地和远程的hotfix1分支
- You are now on branch 'develop' # 切换到develop分支
shengjie@Thinkpad MINGW64 /d/Gitlab/Demos/GitFlow.Demo (develop)
$ git push -u --all # 推送所有分支至远程仓库
$ git push -u --tags # 推送所有tag至远程仓库
经过上面的实操,相信对git flow 有了一定的认识,通过标准的git flow
可以对整个开发过程有更多控制。但相信大家对新的git flow
标准引入的多个分支策略感到复杂,在实际项目当中,根据需要按需使用分支即可。比如,仅使用main
、develop
、feature
分支也是可以的。
GitLab Workflow
GitLab Workflow是在Git Flow的基础之上改进的工作流,一个基本的GitLab 工作流如下图所示。其将代码版本管理与项目和部署管理工具结合起来,使得团队在无缝使用Git的基础上,同时可以进行议题跟踪、请求合并、持续集成和部署。
从图中可以看出,其流程的起点是创建议题。那什么是议题呢,议题对应的是Issue
,对应的是GitLab中的议题
模块。为什么将Issue
翻译为议题,而不是问题呢?因为该模块不仅仅是管理问题清单,还可为功能需求、任务或者要讨论的想法。GitLab中的议题
模块,包含列表、看板、服务台和里程碑三个子功能模块,如下图所示。其中列表用于展示议题列表,看板用于按议题状态分组展示,服务台主要是基于邮件进行议题管理,里程碑可用于项目迭代计划。接下来就来具体看下如何使用议题模块进行项目计划和状态跟踪。
修改配置
在开始之前,需要设置默认分支、受保护分支,设置路径为:设置->仓库。对于刚创建的GitFlow.Demo
项目来说,其默认分支为master,因此如果要实施git flow
,需要将其更改为develop
,如下图所示。其中对于选项:自动关闭默认分支上的引用问题
是指当提交的日志中或合并请求的标题/描述中通过包含指定关键字:fix/fixes/fixed/close/closes/closed/resolve/resolves/resolved #1
完成对Issue #1
的引用,则当完成到默认分支的提交或合并,关联的Issue #1
会自动关闭。
对于受保护分支的设置,其目的是限制指定分支只能通过合并请求进行代码合并来确保分支的稳定性。对于Git flow 中的develop
、main\master
和release
分支而言,都有必要进行分支保护以推行Code Review。
创建标记
在GitLab中,可以通过Label
标记议题和合并请求,进行归类。在项目信息下有个标记子菜单,其允许自行创建或点击生成一组默认的标记
按钮自动生成一组默认的标记,默认标记如下图所示,其中最后一个task
是自行创建的。
创建里程碑
GitLab 里程碑可以用来进行项目计划,比如通过里程碑进行迭代开发。创建里程碑时仅需指定标题、开始时间、截止时间和描述即可。下图中,创建了一个名为学会Git flow基本流程
的里程碑。
创建议题
有了里程碑,就可以对里程碑进行拆分,可以拆分出需求、任务等,创建议题的页面如下图所示,主要录入标题、关联里程碑、指派团队成员、标记及截止日期等。
紧接着就可以通过关联上面的里程碑学会Git flow基本流程
和task
标记创建议题完成对里程碑的拆解,拆解的议题
如下图所示:
创建合并请求
对于合并请求,GitLab提供了配置项,可通过路径为:项目->设置->通用->合并请求,修改合并请求配置,默认配置如下图所示,在实际项目中可以根据需要进行相应修改,比如关闭默认启用'删除源分支'选项
,启用流水线必须成功
、所有讨论都必须解决
的合并检查。
为了方便演示,创建一个新的用户Jeff
,并邀请为项目开发者。创建用户步骤为:管理员->用户->新建用户,邀请用户步骤为:项目信息->成员->邀请成员,如下图所示:
邀请成功后,使用Jeff
账号登录GitLab。打开GitLab.Demo
项目,然后点击项目右上角的派生(Fork)
按钮,创建一个项目的副本到Jeff
自己的仓库中,以实现在不影响原始项目的情况进行更改。
派生(Fork)
成功后的项目,将拥有独立的项目配置,Jeff
可以按照需要配置自己的默认分支和受保护的分支,这里建议仅修改默认分支
为develop
分支即可。修改后,即可将代码克隆(Clone)
到本地并添加对上游仓库(upstream)
的引用以进行代码同步,步骤如下:
shengjie@Thinkpad:~/gitlab$ git clone https://gitlab.shengjie.dev/Jeff/gitflow.demo.git #克隆至本地
shengjie@Thinkpad:~/gitlab$ cd gitflow.demo/
shengjie@Thinkpad:~/gitlab/gitflow.demo$ git remote add upstream https://gitlab.shengjie.dev/demos/gitflow.demo.git # 添加对远程源仓库的引用
shengjie@Thinkpad:~/gitlab/gitflow.demo$ git remote -v
origin https://gitlab.shengjie.dev/Jeff/gitflow.demo.git (fetch)
origin https://gitlab.shengjie.dev/Jeff/gitflow.demo.git (push)
upstream https://gitlab.shengjie.dev/demos/gitflow.demo.git (fetch)
upstream https://gitlab.shengjie.dev/demos/gitflow.demo.git (push)
shengjie@Thinkpad:~/gitlab/gitflow.demo$ git flow init # git flow 初始化
假设Jeff
现在需要负责完成上面创建的第2个议题,也就是:#2: 使用git flow feature 进行特性开发
。那么其可以通过git flow feature start task2
来开展,步骤如下:
shengjie@Thinkpad:~/gitlab/gitflow.demo$ git flow feature start task2 # 创建一个名为task2的feature进行功能特性开发
Switched to a new branch 'feature/task2'
Summary of actions:
- A new branch 'feature/task2' was created, based on 'develop' # 基于develop分支自动创建 fature/task2 分支
- You are now on branch 'feature/task2'
Now, start committing on your feature. When done, use:
git flow feature finish task2
shengjie@Thinkpad:~/gitlab/gitflow.demo$ echo 'Use git glow feautre!' >> readme.txt # 在原有的readme.txt文件上追加一行文字,表示完成task2开发
shengjie@Thinkpad:~/gitlab/gitflow.demo$ cat readme.txt
Hello GitFlow!
Use git glow feautre!
shengjie@Thinkpad:~/gitlab/gitflow.demo$ git commit -am 'fix #2: I have tried git flow feature command' #提交改动
[feature/task2 9b063ac] fix #2: I have tried git flow feature command
1 file changed, 1 insertion(+)
shengjie@Thinkpad:~/gitlab/gitflow.demo$ git flow feature publish # 发布当前feature/task2到个人远程分支
//...
Summary of actions:
- The remote branch 'feature/task2' was created or updated
- The local branch 'feature/task2' was configured to track the remote branch
- You are now on branch 'feature/task2'
将本地feature/task2
分支推送到个人远程仓库后,可打开GitLab确认,如下图所示。
紧接着就可以通过图中的创建合并请求
快捷入口为刚刚的提交创建合并请求,或者通过项目首页右侧的合并请求
菜单创建合并请求。主要分为以下几步:
- 选择源分支和目标分支:这里显然是要从
Jeff/gitflow.demo/feature/task2
分支合并到上游的demos/gitflow.demo/develop
分支,如下图所示:
- 填写合并请求的标题、描述、指定标记和合并人,同时还可以
关联里程碑
来方便负责合并的同事识别本次更改是否为需要此时合并到本次待发布的分支,另外如果勾选下图中的Delete source branch when merge request is accepted.(当合并请求通过后删除源分支)
,则当请求完成合并,源分支自动关闭。如下图所示:
- 合并请求。源分支的管理员,会在右上角收到合并请求的消息通知,点击打开,确认变更内容后,即可点击
合并
按钮进行合并。其中可以勾选删除源分支
,则当成功合并后,源分支也就是Jeff:feature/task2
会自动删除,同时由于使用了fix #2
关键字将合并请求关联到了#2 Issue,因此成功合并后,Issue也会自动关闭。
创建发布
GitLab 也贴心的提供了在线发布功能,可通过路径:部署->发布->新建发布,进行在线版本发布。通过选择发布的标签,关联里程碑,填写发布说明,后点击创建发布即可,步骤如下图1所示,创建成功后,会看到如下图2的发布详情。以上就是Git flow 结合GitLab的基本流程,下一节就来介绍下GitLab CI/CD,来领略GitLab 工作流的真正威力。