GitLab 是一个类似于 GitHub 的开源源码托管服务,它除了提供基于 git 的基本代码托管服务外。还具备很多与软件开发协作相关的其他功能。比如 issues、Merge Requests 等。
利用 GitLab 提供的这些功能,我们可以实践一些简单的项目管理和协作流程。这套流程借鉴于很多成功的开源项目,非常适合在小型开发团队里面使用。
使用 issues 来管理需求与缺陷
GitLab issues 类似于“工单系统”,是一个发布项目相关信息的地方。项目的所有成员都可以创建新的 issue,其他成员可以在 issue 下进行相关的讨论。
issues 本身是一个非常简单的功能,但是如果配合 “标签”、“里程碑” 等功能一起使用,就可以承担起一定的项目管理工作。
录入 issue
在项目的开发过程中,我们会碰到很多新的需求、软件 bug 等。这些需求与 bug ,就是 issue 最大的来源,它们都可以作为 issue 录入到项目的 issues 中。
因为 issue 的录入门槛很低,鼓励项目成员录入 issue 后,项目很容易就会出现大量的 issues。所以我们应该严格控制每个 issue 的内容质量,确保其他人可以通过这个 issue 获取足够多的信息,提高沟通效率。
不光是和需求和 bug,任何和项目有关的内容都可以录入到 issue 中。
编写优秀的“需求” issue
如果你要录入一个需求类的 issue,最好在内容主体中包含下面这些内容:
- 用一句话描述你的需求,并用它作为标题
- 这个需求是解决什么问题的?
- 这个需求对软件现有功能会造成什么影响?
- 这个需求应该实现什么样的功能?
- 这个需求是否依赖其他模块提供相关支持?
- [可选] 这个需求有哪些实现方式?
- [可选] 这些可选的实现方式分别有哪些优缺点?
编写优秀的“bug” issue
如果你要录入一个 bug issue,最好在内容主体中包含下面这些内容:
- 提供出现问题的软件版本号、操作系统环境等相关信息
- 提供能够稳定复现问题的相关步骤
- 描述期待行为与当前行为
- [可选] 你对这个 bug 原因的相关分析
Review issue 并为其打上标签
当 issue 被创建后,应该等待项目的 owner (owner 指项目的所有者,是对项目各方面都比较了解的人,可以为多个人) 对 issue 进行 Review。
Review 时,如果 owner 觉得这个 issue 满足下面的任意条件:
- 与项目本身的功能、市场定位有冲突
- 与现存 issue 有重复
- 其他不应该被保留的情况
则应该在评论中说明相关情况,并关闭该 issue。如果经过上面的过滤后,觉得 issue 应该被继续跟进,那就应该为它打上标签,方便之后的筛选、排期等工作。
“标签”是 issue 的核心特性,为了更好的使用它,我建议采用 "{type}/{value}" 这样的二维标签来取代传统的 "{value}" 单维标签,下面是一些常用的 issue 标签:
优先级:priority
优先级(priority)是最重要的标签之一。它直接影响 bug 需要被响应的速度、或需求的具体排期。 (经由 @云掩大椿 提醒,已修改为更符合惯例的定义)
priority/P0
:十分紧急priority/P1
:较为紧急priority/P2
:普通priority/P3
:不紧急
类型:kind
kind(类别)表示 issue 属于哪种类型。
kind/bug
:软件缺陷kind/feature
:新功能kind/enhancement
:改进项,模块代码重构等不影响项目功能但是改善工程质量的 issue 可归入此类kind/research
:技术调研类,一般以输出某类结论或报告视为结束
工作量:size
size(工作量)表示 issue 需要大约花费多少时间/精力,可以用来做简单的工作量评估参考。
size/XL
size/M
size/SM
领域/模块:area
area用于标记当前 issue 属于项目中的什么领域/模块。这个分类下的具体标签由项目本身决定。比如 area/apiserver
、area/controller
等。给 issue 打上 area 标签后,项目不同模块的相关负责人可以更方便的找到自己负责的相关 issues。
GitLab 的标签是一个非常灵活的功能,在具体使用中,不必拘泥于上面列出来的这几种标签,可以根据当前项目特点随意调整。
issue 的后续操作
当 issue 被创建、打上标签以后,就可以进行后续操作了。issue 的后续操作主要包括下面几种:
认领 issue
:每一个 issue 都有一个 Assignee(受理人),表示当前 issue 由谁在处理。在你准备开始具体的工作前,一定要记得将 issue 认领为自己所有。在 issue 下进行讨论
:在 issue 下可以围绕 issue 进行讨论,在讨论过程中,可以通过 @USERNAME 的方式通知其他人关注当前 issue。
使用 issue 做项目里程碑管理
除了为 issue 打上标签以外,你还可以为 issue 绑定上 milestone(里程碑),来将 issue 与某些特定的项目节点关联起来。之后便可以在 milestones 页面查看每一个里程碑的进展。
和 labels 一样,里程碑也是一个十分灵活的功能,你可以根据项目需要建立不同的里程碑,比如:
基于软件版本号
:基于未来将要发布的版本号建立里程碑,比如v1.0.3
、v2.0.1
等等基于时间周期
:基于特定的时间周期 - 比如敏捷开发中的一个 sprint - 来建立里程碑,比如Y2017-M7W3
、Y2017-M7W4
等等
使用 issue board
使用 issue board(类似于敏捷开发中的“看板”),可以在一个页面看到当前处于不同阶段的所有 issues。这个功能非常适合站立晨会时使用。
勤于关闭 issues
随着项目越来越大,项目累积的 issue 也会越来越多。而这些 issue 中有很多已经失去它的价值。
所以,为了避免有价值的 issue 淹没在这些过时的信息当中,我们应该定期 Review 现有的 issues,关闭掉那些已经过时的 issues。
基于 Merge Request 的开发流程
在 GitLab 上创建的项目,所有人都不应该直接往 master 分支推送代码。而是应该在其他分支(或者 fork 项目的分支)进行开发。并最终通过创建 Merge Request(类似 GitHub pull request)将代码合并到 master 分支。
创建 Merge Request 并进行 Code Review
基于 MR 的开发流程如下:
- 开发者在自己的分支下进行开发,开发完成后,创建将该分支合并到 Master 的 Merge Request,改动进入 Review 状态
- 进入 Review 状态的代码,将由团队内的其他一位成员(经验比较丰富、或者对该工作模块比较熟悉)对代码改动进行 Code Review
- 大家对 Reivew 结果进行讨论,并提交新的修改
- 最终达成一致后,代码被 Merge 进 Master 分支
灵活创建新分支来避免 MR 冲突
我们一般会用类似于 dev_piglei
这样的分支名称进行开发,遵循着 “开发” -> “push 并创建 MR” -> “开发” 这样的工作流程。
但是,因为一个分支是严格对应到一个 MR 的,当你在同一个分支上开发不同功能时,如果 MR 一直处于 open 状态,那这些不同功能都会被推送到同一个 MR 上,对 Review 过程产生困扰。
为了避免这种情况,最好为不同的功能项创建不同的分支并各自创建 MR,比如 dev_feature_add_member
、dev_feature_disabled_user
。
在 git 工作流方面,git-flow workflow 是一个值得学习的内容
分拆大的 Merge Request
如果开发一些比较大的需求,我们通常会将他们一次实现完,然后作为一个大的 MR 来提交 Review。
但是如果每个 MR 过于复杂,会大大影响 Code Review 的效率。所以,如果你要实现一个比较复杂的特性,建议将它拆解为多个比较小的 MR 来依次提交。
假如,你要为网站的 feed 页面从零开始添加 redis 缓存功能。可能一开始想的提交这个大 MR:
- [MR] 添加基于 redis 的缓存模块并为 feed 页面添加缓存并主动过期
但这个 MR 里面包含了太多内容,会增加 Review 的难度。所以可以试着将这个功能拆解为下面三个更小的 MR:
- [MR] 添加基于缓存模块
- [MR] 为缓存模块添加 Redis 作为存储后端
- [MR] 为 feed 页面提供缓存,并主动过期
谨记:
- 超过 1000 行的代码改动 Review 起来非常困难
- 可以使用 feature flag(功能开关)在 PR 完全完成前屏蔽部分功能
😊 如果你喜欢这篇文章,也欢迎了解我的书: 《Python 工匠:案例、技巧与工程实践》 。它专注于编程基础素养与 Python 高级技巧的结合,是一本广受好评、适合许多人的 Python 进阶书。