事先声明,纯纯做记录用,如果有哪里说的不对请留一下言哦!

# 前言

由于我自己之前完全没有接触过相对 系统性 的 github 协作开发,而最近在实习的过程中技术主管和我科普了一下比较符合实际的规范协作流程,于是我想着写一篇文章来总结一下。

首先我们需要知道在一个项目中,你如果是作为团队的一员,那么所有的分支、issue 以及 PR 都应该是以 你所完成的单个功能 为单位。一个个 功能 的不断被实现,最终拼凑出一个完整的项目。而且以功能作为协作开发的单位的话,也使得整个项目变得比较容易去追溯维护。如果某个功能出现了问题,直接去找实现这个功能的成员就可以了。

# Github 提供的项目工具

首先我们可以看一下 github 中一个项目的主要界面 tabs:

image-20240221143027311

  • Code: 整个项目的代码资源。
  • Issue: 这个项目当前需要完成、处理的一些功能、bug 修复等。在这里就是对这个项目进行计划的声明的,说明接下来要完成什么事情。 这个是最最最基本的团队协作的工具。
  • Pull requests: 就是 PR。一般团队成员从 main 分支拉取了最新的内容之后,便 checkout 到他们自己的分支上进行开发。当功能初步测试完成,开发完毕后,便可以远程提交到仓库的这个分支上,然后提交一个 PR, 表示我目前的活已经干完了,要和 main 合并。
  • Actions: 就是 Github workflow,github 工作流。一般就用于 CI/CD 的一些操作,或者提 PR 后和 main 进行 merge 之前的一些验证操作。
  • Projects: 是一个项目管理工具,可以创建多个项目看板来跟踪不同方面的工作。每个项目看板都可以包含多个列,这些列代表任务的不同阶段,如 “待办事项”、“进行中”、“已完成” 等。 不过目前在 Github 上面用这个的好像比较少,更多的都是在自己团队内部的一些工单软件中统筹的,比如飞书的工单推进。
  • Security: 主要就是用来维护整个项目的安全性的,平时用的也比较少。旨在帮助开发者发现并修复安全漏洞。
  • Insights: 和它的名字一样,就是用来统计汇总关于这个项目的全部数据的。它提供了一系列的统计数据和视图,帮助开发者和项目维护者理解项目的健康状况、贡献者活动和其他重要指标。

# 一般流程梳理

# 任务到功能

我们如果自己作为团队成员,我们的技术负责人会给我们派发一些开发的任务。 我们首先第一件事就是把这个一个任务拆成功能。 一般而言,如果是相对比较合格的技术负责人,给自己的员工派任务都是以功能为单位进行的。我们如果作为个人开发者,做自己个人的项目, 保持这样的习惯也是非常好的。

比如目前突然有个新项目的 UI 画好了,然后技术负责人找你说你一个人 把这整个项目的 UI 全部画了 ,这就是一个新任务。有些项目的 UI 是非常复杂难画的,可能一天画不完,这个时候就是要将其拆成一个个功能的实现。比如你可以按照一个个页面进行 UI 绘制,把每个页面的 UI、基础互动功能、假数据全部完成作为这个页面的绘制功能实现。

# 功能到 Issue

功能确认完毕,开始进行 Issue 的编写。Issue 分 OpenClose 。Open 的 Issue 就是目前正在推进中的任务,Close 的表示已经完成了。

image-20240221145805969

Issue 应该是以 任务 为单位,也就是说你每一次和负责人沟通完毕或者你自己打算给自己的个人项目开工的时候,你就应该 new 一个 Issue。我们可以看一下 Issue 界面:

image-20240221151051438

可以看到每个 Issue 主要由 Issue 名称、Issue Tags、Issue 的描述内容、Issue 对应的 PR、Issue 的负责人组成。

  • Issue 名称:取名方式和一般的团队协作 commit 方式差不多,也是以 feat、fix、chore 等开头,后面的括号是指定这个功能对应的项目名称(Monorepo 等多项目单仓库管理模式适用,如果是涉及到项目全局的一些功能实现就用 all)。后面跟 **: ** ,然后写这个 Issue 对应的任务名。

  • Issue Tags: 这就是给每个 Issue 打标签,标明这个 Issue 是啥类型的。

    image-20240221150543101

    标签是团队内部一起指定的,可以根据实现任务的类型、所处理的不同项目等进行分类。github 内置的标签就是以任务类型来分的。一个 Issue 得携带标签,标明这个任务的性质是什么,对应的是哪个项目,方便后续的维护与项目进度统筹。

  • Issue 的描述内容:这里一般是以 markdown 中任务列表 的格式进行书写,也就是 - [ ] <功能实现需求> 的格式。每一条任务就代表着这个任务所拆分出来的每一个功能,你接下来的开发就是对着这几个功能进行开发,本地完成了之后就给这个功能打勾。

  • Issue 对应的 PR: 每一个功能的完成都应该对应着一个 PR,在后面可以加上 # 来触发对于 PR 的选择。 我们在完成了一个功能之后,确认无误就可以提交到远程分支然后提个 PR 了。提了之后,就可以到你自己刚刚的 Issue,勾掉你的任务,然后在任务后面加一个 #,选择 PR。

  • Issue 的负责人:就是上面的 Assignees。一般你自己 new 出来你自己新的 issue,负责人一般也就是你;如果你的技术负责人分派给你任务并且提前新建好了 Issue,他可能就会指定你为 Assignees。

另外提一嘴,我们可以看到 Labels 按钮旁边有个按钮叫 Milestone(里程碑),这个是什么呢?这个是 专门用来对 Issue 进行分类管理的一个容器 。我们可以点击进入:

image-20240224115237055

需要填写这个里程碑的标题、截止日期以及这个里程碑的描述。

我们知道 Issue 是对单个任务的实现的描述,而里程碑则是用来管理多个 Issue,而这多个 Issue 就共同组成了一个 版本 的功能实现。

也就是说,一个 Milestone 代表着一个版本的实现。而这个版本中所涉及到的全部 Issue,就全部放在这里面。

image-20240224115614054

比如我这边就创建了一个 V1 版本的实现,接下来就是把对应的 Issue 加到对应的 Milestone 中就可以了。我们直接去 Issue 的主界面,然后选择右侧的 Milestone 即可。

image-20240224115742939

这样就完成了比较正式的项目跟进操作。

# Issue 到 PR

到这一步意味着你得正式开始干活了。

  1. 你需要从 main 分支切出一个新分支,这个分支的命名就代表着你当前决定要处理的 功能 (不是任务)。

  2. 然后你开始干活。这是一个比较漫长且辛苦的过程。

  3. 干完活并且本地测试可以跑通之后就可以进行 commit 了。commit 的话必须要遵循团队的 commit 规范,一般是通过 commitlint+husky 等的管理工具进行 commit 信息的校验,只有符合格式的才能够通过校验成功 commit。

  4. 成功 commit 之后就可以提交到远程的分支,最后就是提 PR 了。上面其实已经讲的差不多了,不过有一些细节补充一下。

image-20240221153833232

和 Issue 的 #相对应,在 PR 中你可以在 PR 描述中描述清楚你干了什么,最后加一个 close #<Issue编号> 来自动触发 Merge 后删除 Issue 的功能。 不过这个只在最后的 PR 完成了一整个 Issue 的所有任务后进行,其他时间就无需使用。

顺带一提,这边可以看到一个 PR 有两个 Check,这个是通过 Github 的 workflow 进行配置的。具体的配置方式也是按照团队的不同来进行。

# PR 到 main

当技术负责人或者你自己将你的 PR 合并到 main 上之后,直接把这个远程分支删掉,然后你把本地的分支删掉,最后切换到 main 再把最新的远程 main 分支内容 pull 到本地,确保下一次任务开始之前你本地的代码是最新的,避免了冲突的风险。

# 最后

这样子就完成了一个比较基本的开发流程,接下来的每一步开发就是按照这样的流程循环进行。

当然,如果你的项目只有你一个人开发,那么你也可以按照这样的流程来走,不过可以进行一定程度的简化。 我个人觉得自己开发的时候也遵循这样的流程对未来的开发积累是非常有利的,虽然在一定程度上会降低开发的效率。