前端小微团队的Gitlab实践

疫情期间我感受整我的懒散了很多,慢慢有意识要振做起来了,恢复到正常的节奏。最近团队代码库从Gerrit迁移到了Gitlab,为了让前端团队平常开发工做有条不紊高效运转,开发历史可追溯,我也查阅和学习了很多资料。参考业界主流的Git工做流,结合公司业务特质,我也梳理了一套适合本身团队的Git工做流,在这里作下分享。前端

分支管理

首先要说的是分支管理,分支管理是git工做流的基础,好的分支设计有助于规范开发流程,也是CI/CD的基础。git

分支策略

业界主流的git工做流,通常会分为develop, release, master, hotfix/xxx, feature/xxx等分支。各个分支各司其职,贯穿了整个开发,测试,部署流程。我这里也基于主流的分支策略作了一些定制,下面用一张表格简单归纳下:shell

分支名 分支定位 描述 权限控制
develop 开发分支 不能够在develop分支push代码,应新建feature/xxx进行需求开发。迭代功能开发完成后的代码都会merge到develop分支。 Develper不可直接push,可发起merge request
feature/xxx 特性分支 针对每一项需求,新建feature分支,如feature/user_login,用于开发用户登陆功能。 Develper可直接push
release 提测分支 由develop分支合入release分支。ps: 应配置此分支触发CI/CD,部署至测试环境。 Maintainer可发起merge request
bug/xxx 缺陷分支 提测后发现的bug,应基于develop分支建立bug/xxx分支修复缺陷,修改完毕后应合入develop分支等待回归测试。
master 发布分支 master应处于随时可发布的状态,用于对外发布正式版本。ps: 应配置此分支触发CI/CD,部署至生产环境。 Maintainer可发起merge request
hotfix/xxx 热修复分支 处理线上最新版本出现的bug Develper可直接push
fix/xxx 旧版本修复分支 处理线上旧版本的bug Develper可直接push

通常来讲,develop, release, master分支是必备的。而feature/xxx, bug/xxx, hotfix/xxx, fix/xxx等分支纯属一种语义化的分支命名,若是要简单粗暴一点,这些分支能够不分类,都命名为issue/issue号,好比issue/1,可是要在issue中说明具体问题和待办事项,保证开发工做可追溯。npm

保护分支

利用Protected Branches,咱们能够防止开发人员错误地将代码push到某些分支。对于普通开发人员,咱们仅对develop分支提供merge权限。json

保护分支

具体操做案例请前往下面的实战案例一节查看。并发

issue驱动工做

咱们团队采用的敏捷开发协做平台是腾讯的TAPD,平常迭代需求,缺陷等都会在TAPD上记录。为了让Gitlab代码库能与迭代平常事务关联上,我决定用Gitlab issues来作记录,方便追溯问题。ide

里程碑

里程碑Milestone能够认为是一个阶段性的目标,好比是一轮迭代计划。里程碑能够设定时间范围,用来约束和提醒开发人员。gitlab

milestones

里程碑能够拆解为N个issue,新建issue时能够关联里程碑。好比这轮迭代一共5个需求,那么就能够新建5个issue。在约定的时间范围内,若是一个里程碑关联的全部issueClosed掉了,就意味着目标顺利达成。post

建立issue

标签

Gitlab提供了label来标识和分类issue,我以为这是一个很是好的功能。我这里列举了几种label,用来标识issue分类紧急程度单元测试

标签管理

issue分类

全部的开发工做应该经过issue记录,包括但不限于需求缺陷开发自测试用户体验等范畴。

需求&缺陷

这里大概又分为两种状况,一种是TAPD记录在案的需求和缺陷,另外一种是与产品或测试人员口头沟通时传达的简单需求或缺陷(小公司会有这种状况...)。

对于TAPD记录的需求和缺陷,建立issue时应附上连接,方便查阅(上文中已有提到)。

对于口头沟通的需求和缺陷,我定了个规则,要求提出人本人在Gitlab上建立issue,并将需求或缺陷简单描述清楚,不然口头沟通的开发工做我不接(也是为了不过后扯皮)。

ps:其实要求产品或者测试提issue,还不如上Tapd记录。我定这么个规则,其实就是借Gitlab找个说辞,杜绝口头类需求或缺陷,哈哈。

开发自测试

开发者本身发现了系统缺陷或问题,此时应该经过issue记录问题,并建立相应分支修改代码。

自测试issue

实战案例

我前面也说了,个人原则是issue驱动开发工做。

下面用几个例子来简单说明基本的开发流程。小公司里整个流程比较简单,没有复杂的集成测试,多轮验收测试,灰度测试等。我甚至连单元测试都没作(捂脸...)。

公共库和公共组件实际上是颇有必要作单元测试的,这里立个flag,后面必定补上单元测试。

需求开发

feature/1,一个特性分支,对应issue 1

建立需求

正常的需求固然来源于产品经理等需求提出方,因为是经过示例说明,这里我本身在TAPD上模拟着写一个需求。

TAPD建立需求

建立issue

建立Gitlab issue,连接到TAPD中的相关需求。

建立issue

一个issue

建立分支&功能开发

基于develop分支建立feature分支进行功能开发(要保证本地git仓库当前处于develop分支,且与远程仓库develop分支同步)。

git checkout -b feature/1

或者直接以远程仓库的develop分支为基础建立分支。

git checkout -b feature/1 origin/develop

ps:我这里用的feature/1做为分支名,其实这里的1是用的issue号,并无用诸如feature/login_verify之类的名字,是由于我以为用issue号能够更方便地找到对应的issue,更容易追踪代码。

接着咱们开始开发新功能......

快乐地撸代码

commit & push

完成功能开发后,咱们须要提交代码并同步到远程仓库。

PS D:\projects\gitlab\project_xxx> git add .
PS D:\projects\gitlab\project_xxx> git cz
cz-cli@4.0.3, cz-conventional-changelog@3.1.0

? Select the type of change that you're committing: feat:     A new feature
? What is the scope of this change (e.g. component or file name): (press enter to skip)
? Write a short, imperative tense description of the change (max 94 chars):
 (9) 登陆校验功能
? Provide a longer description of the change: (press enter to skip)

? Are there any breaking changes? No
? Does this change affect any open issues? Yes
? If issues are closed, the commit requires a body. Please enter a longer description of the commit itself:
 -
? Add issue references (e.g. "fix #123", "re #123".):
 fix #1

git push origin HEAD

git cz是利用了commitizen来替代git commit。详情请点击前端自动化部署的深度实践深刻了解。

fix #1用于关闭issue 1

git push origin HEAD则表明推送到远程仓库同名分支。

建立Merge Request

开发人员发起Merge Request,请求将本身开发的功能特性合入develop分支。

建立Merge Request

接着Maintainer须要Review代码,确认无误后赞成Merge。而后这部分代码就在远程Git仓库入库了,其余开发同窗拉取develop分支就能看到了。

版本提测

issue/2,处理更新日志,版本号等内容,对应issue 2

每一个团队的开发节奏都不一样,有的团队会每日持续集成发版本提测,有的可能两天一次,这个就不深刻讨论了......

那么当咱们准备提测时,应该怎么作呢?

经过上节的了解,咱们已经知道,迭代内的功能需求都会经过feature/xxx分支合入到develop分支。

提测前,通常来讲,仍是要更新下CHANGELOG.mdpackage.json的版本号,能够由Maintainer或其余负责该项事务的同窗执行。

主要是执行npm version major/minor/patch -m 'something done',具体操做能够参考 前端自动化部署的深度实践一文。
git checkout -b issue/2 origin/develop
npm version minor -m '迭代1第一次提测'
git push origin HEAD
而后发起merge request合入develop分支

此时,应以最新的develop分支代码在开发环境跑一遍功能,保证版本自测经过。

提测时,由Maintainer发起Merge Request,将develop分支代码合入release分支,此时自动触发Gitlab CI/CD,自动构建并发布至测试环境

版本提测后,各责任人应在TAPD上将相关需求和缺陷的状态变动为“测试中”

修复测试环境bug

bug/3,一个bug分支,对应issue 3

这里说的是在迭代周期内由测试工程师发现的测试环境中的系统bug,这些bug会被记录在敏捷开发协做平台TAPD上。修复测试环境bug的步骤与开发需求相似,这里简单说下步骤:

  1. 在Gitlab上建立issue

    建立issue,并附上TAPD上的缺陷连接,方便追溯
  2. 建立分支&修复缺陷

    基于develop分支建立分支:

    // 3是issue号
    git checkout -b bug/3 origin/develop

    接着改代码......

  3. commit & push

    PS D:\projects\gitlab\project_xxx> git cz
    cz-cli@4.0.3, cz-conventional-changelog@3.1.0
    
    ? Select the type of change that you're committing: fix:      A bug fix
    ? What is the scope of this change (e.g. component or file name): (press enter to skip)
    ? Write a short, imperative tense description of the change (max 95 chars):
     (11) 修复一个测试环境bug
    ? Provide a longer description of the change: (press enter to skip)
    
    ? Are there any breaking changes? No
    ? Does this change affect any open issues? Yes
    ? If issues are closed, the commit requires a body. Please enter a longer description of the commit itself:
     -
    ? Add issue references (e.g. "fix #123", "re #123".):
     fix #3
     
    git push origin HEAD
  4. 发起Merge Request

    开发人员发起Merge Request,请求将本身修复缺陷引入的代码合入develop分支。

    而后Maintainer须要Review代码,赞成本次Merge Request

  5. 等待回归测试

    bug将在下一次CI/CD后,进入回归测试流程。

  6. 级别高的测试环境Bug

    若是是级别很高的bug,好比影响了系统运行,致使测试人员没法正常测试的,应以release分支为基础建立bug分支,修改完毕后合入release分支,再发起cherry pick合入develop分支。

发布至生产环境

通过几轮持续集成和回归测试后,一个迭代版本也慢慢趋于稳定,此时也迎来了激动人心的上线时间。咱们要作的就是把经过了测试的release分支合入master分支。

release合入master

这一步相对简单,可是要特别注意权限控制(防止生产环境事故),具体权限控制能够回头看第一章节分支管理

release分支相似,master分支自动触发Gitlab CI/CD,自动构建并发布至生产环境

线上回滚

revert/4,一个回滚分支,对应issue 4

代码升级到线上,可是发现报错,系统没法正常运行。此时若是不能及时排查出问题,那么只能先进行版本回退操做。

先说说惯性思惟下,个人版本回退作法。

首先仍是建立issue记录下:

建立记录回滚的issue

基于master分支建立revert/4分支

git checkout -b revert/4 origin/master

假设当前版本是1.1.0,咱们想回退到上个版本1.0.3。那么咱们须要先查看下1.0.3版本的信息。

PS D:\tusi\projects\gitlab\projectname> git show 1.0.3
commit 90c9170a499c2c5f8f8cf4e97fc49a91d714be50 (tag: 1.0.3, fix/1.0.2_has_bug)
Author: tusi <tusi@xxx.com.cn>
Date:   Thu Feb 20 13:29:31 2020 +0800

    fix:1.0.2

diff --git a/README.md b/README.md
index ac831d0..2ee623b 100644
--- a/README.md
+++ b/README.md
@@ -10,6 +10,8 @@

 只想修改旧版本的bug,不改最新的master

+1.0.2版本仍是有个版本,再修复下
+
 特性2提交

 特性3提交

主要是取到1.0.3版本对应的commit id,其值为90c9170a499c2c5f8f8cf4e97fc49a91d714be50

接着,咱们根据commit id进行reset操做,再推送到远程同名分支。

git reset --hard 90c9170a499c2c5f8f8cf4e97fc49a91d714be50
git push origin HEAD

接着发起Merge Requestrevert/4分支合入master分支。

回滚分支合入master

通常来讲,这波操做没什么问题,能解决常规的回滚问题。

临时变通

因为master分支是保护分支,设置了不可push。若是不想经过merge的方式回滚,因此只能先临时设置Maintainer拥有push权限,而后由Maintainer进行回滚操做。

git checkout master
git pull
git show 1.0.3
git reset --hard 90c9170a499c2c5f8f8cf4e97fc49a91d714be50
git push origin HEAD

完过后,还须要记得把master设置为不可push

Q: 为何不让 Maintainer一直拥有 masterpush权限?

A: 主要仍是为了防止出现生产环境事故,给予临时性权限更稳妥!

git reset --hard存在什么问题?

如题,git reset --hard确实是存在问题的。git reset --hard属于霸道玩法,直接移动HEAD指针,会丢弃以后的提交记录,若是不慎误操做了也别慌,仍是能够经过查询git reflog找到commitId抢救回来的;git reset后还存在一个隐性的问题,若是与旧的branch进行merge操做时,会把git reset回滚的代码从新引入。那么怎么解决这些问题呢?

束手无策

别慌,这个时候你必须掏出git revert了。

Q: git revert的优点在哪?

A: 首先,git revert是经过一次新的commit来进行回滚操做的,HEAD指针向前移动,这样就不会丢失记录;另外,git revert也不会引发merge旧分支时误引入回滚的代码。最重要的是,git revert在回滚的细节控制上更加优秀,可解决部分回滚的需求。

举个栗子,本轮迭代团队共完成需求2项,而上线后发现其中1项需求有致命性缺陷,须要回滚这个需求相关的代码,同时要保留另外一个需求的代码。

我太难了

首先咱们查看下日志,找下这两个需求的commitId

PS D:\tusi\projects\test\git_test> git log --oneline
86252da (HEAD -> master, origin/master, origin/HEAD) 解决冲突
e3cef4e (origin/release, release) Merge branch 'develop' into 'release'
f247f38 (origin/develop, develop) 需求2
89502c2 需求1

咱们利用git revert回滚需求1相关的代码

git revert -n 89502c2

这时可能要解决冲突,解决完冲突后就能够push到远程master分支了。

git add .
git commit -m '回滚需求1的相关代码,并解决冲突'
git push origin master

感受仍是菜菜的,若是大佬们有更优雅的解决方案,求指导啊!

修复线上bug

hotfix/5,一个线上热修复分支,对应issue 5

好比线上出现了系统没法登陆的bug,测试工程师也在TAPD提交了缺陷记录。那么修复线上bug的步骤是什么呢?

  1. 建立issue,标题能够从TAPD中的Bug单中copy过来,而描述就贴上Bug单的连接便可。
  2. 基于master分支建立分支hotfix/5

    git checkout -b hotfix/5 origin/master
  3. 撸代码,修复此bug......
  4. 修复完此bug后,提交该分支代码到远程仓库同名分支

    git push origin HEAD
  5. 而后发起cherry pick合入到masterdevelop分支,并在master分支打上新的版本tag(假设当前最大的tag1.0.0,那么新的版本tag应为1.0.1)。

修复线上旧版本bug

fix/6,一个线上旧版本修复分支,对应issue 6

某些项目产品可能会有多个线上版本同时在运行,那么不可避免要解决旧版本的bug。针对线上旧版本出现的bug,修复步骤与上节相似。

  1. 建立issue,描述清楚问题
  2. 假设当前版本是1.0.0,而0.9.0版本出了一个bug,应基于tag 0.9.0建立fix分支。

    git checkout -b fix/6 0.9.0
  3. 修复缺陷后,应打上新的tag 0.9.1,并推送到远程。

    git tag 0.9.1
    git push origin tag 0.9.1
  4. 若是此bug也存在于最新的master分支,则须要git push origin HEAD提交该fix分支代码到远程仓库同名分支,而后发起cherry pick合入到master,此时很大可能存在冲突,须要解决冲突。

    cherry pick

cherry pick

在了解到cherry pick以前,我一直认为只有git merge能够合并代码,也好几回遇到合入了不想要的代码的问题。有了cherry pick,咱们就能够合并单次提交记录,解决git merge时合并太多不想要的内容的烦恼,在解决bug时特别有用。

git rebase

通过这段时间的使用,我发现使用git merge合并分支时,会让git logGraph图看起来有点吃力。

PS D:\tusi\projects\gitlab\projectname> git log --pretty --oneline --graph
*   7f513b0 (HEAD -> develop) Merge branch 'issue/55' into 'release'
|\
| * 1c94437 (origin/issue/55, issue/55) fix: 【bug】XXX1
| *   c84edd6 Merge branch 'release' of host:project_repository into release
| |\
| |/
|/|
* |   115a26c Merge branch 'develop' into 'release'
|\ \
| * \   60d7de6 Merge branch 'issue/30' into 'develop'
| |\ \
| | * | 27c59e8 (origin/issue/30, issue/30) fix: 【bug】XXX2
| | | *   ea17250 Merge branch 'release' of host:project_repository into release
| | | |\
| |_|_|/
|/| | |
* | | |   9fd704b Merge branch 'develop' into 'release'
|\ \ \ \
| |/ / /
| * | |   a774d26 Merge branch 'issue/30' into 'develop'
| |\ \ \
| | |/ /

接着我就了解到了git rebase,变基,哈哈哈。因为对rebase了解不深,目前也不敢轻易改用rebase,毕竟rebase仍是有不少隐藏的坑的,使用起来要慎重!在这里先挖个坑吧,后面搞懂了再填坑......

注意事项

  1. 通常而言,本身发起的Merge Request必须由别的同事Review并赞成合入,这样更有利于发现代码问题。
  2. 对了,TAPD还支持与Gitlab协同的。详情见源码关联指引

结语

实践证实,这套Git工做流目前能覆盖我项目开发过程当中的绝大部分场景。不过要注意的是,适合本身的才是最好的,盲目采用别人的方案有时候是会水土不服的。

以上所述纯属前端小微团队内部的Gitlab实践,必然存在着不少不足之处,若有错误之处还请指正,欢迎交流。

欢迎关注&交流

相关文章
相关标签/搜索