commitlint
相信大家对 Git 并不陌生,不知大家是否有过这种经历,自己提交 git commit msg 自己却看不懂。在小的团队里,可能我们更注重的是业务产出,并不在乎这些细节。随着团队的壮大,commit msg 规范化至关重要,他意味着我们是否清楚自己和同事对代码干了什么,在代码排错、回滚甚至是甩锅时起到了关键性作用。
在正式集成 commitlint 之前,先要介绍一下git hooks (opens new window), 顾名思义 hooks 为“钩子”之意,它是“发布订阅模式”的一种实现,和前端中的 DOM 事件(click、hover 等)相似,Git 也预先定义了一些“事件钩子”如“commit-msg”、“pre-commit”等,当我们执行对应的 Git 操作时会触发它们,从而通知订阅该事件的 shell script 文件处理我们要进行的任务,这些 shell 脚本文件存放在项目根目录下的.git/hooks 目录中,如图所示:
我们可以通过编写这些 shell script 文件定制我们的校验任务,但前端工程师大多对 linux/windows shell 并不擅长,这和我们平时的工作重心有关, 因此我们通过编写 git hooks 脚本来优化前端工作流的这条道路十分艰难。Nodejs 改变了这一切,它让 JavaScript 拥有了控制“操作系统”的能力,你只需要安装 nodejs 包husky (opens new window),它会帮我们自动生成.git/hooks 目录下的 shell script,我们便可以很轻松的使用更熟悉的 Nodejs 处理 git hooks 任务,而无需关注 shell script 的实现细节。
执行下面命令, 在开发环境中安装 husky,如下所示:
npm install husky --save-dev
在项目根目录下 package.json 文件中添加如下配置,并在 hooks 字段下添加 git hooks 监听任务配置, 如下:
// 这是NPM原生支持的脚本执行定义,当执行“npm run 脚本名”时执行
"scripts": {
"test": "node test.js"
},
// 这是husky扩展的脚本执行的定义方式,当对应git hooks触发时执行
"husky": {
"hooks": {
// 可以执行一个js文件,将控制权转移给我们更熟悉的nodejs
"pre-commit": "node heihei.js",
// 也可以调用其他脚本或者执行一段原生shell命令
"commit-msg": "npm run test && echo succeed"
}
}
上面的配置只作为测试例子之用,无需真正集成到项目中
# 安装 commitlint
首先安装 @commitlint/cli 和 @commitlint/config-conventional
npm install @commitlint/cli --save-dev
npm install @commitlint/config-conventional --save-dev
- @commitlint/cli 是 commitlint 提供的命令行工具,安装后会将 cli 脚本放置在./node_modules/.bin/目录下
- @commitlint/config-conventional 是社区中一些共享的配置,我们可以扩展这些配置,也可以不安装这个包自定义配置
接下来是初始化@commitlint/cli 的配置文件,在项目根目录创建名为 commitlint.config.js 的文件,代码如下:
/**
* feature:新功能
* update:更新某功能
* fixbug:修补某功能的bug
* refactor:重构某个功能
* optimize: 优化构建工具或运行时性能
* style:仅样式改动
* docs:仅文档新增/改动
* chore:构建过程或辅助工具的变动
*/
module.exports = {
extends: ["@commitlint/config-conventional"],
rules: {
"type-enum": [
2,
"always",
[
"feature",
"update",
"fixbug",
"refactor",
"optimize",
"style",
"docs",
"chore",
],
],
"type-case": [0],
"type-empty": [0],
"scope-empty": [0],
"scope-case": [0],
"subject-full-stop": [0, "never"],
"subject-case": [0, "never"],
"header-max-length": [0, "always", 72],
},
};
// 这些配置是什么意思?请自行查阅commitlint文档
最后我们需要在 package.json 中配置上我们的 husky 的选项,代码片段如下:
"scripts": {
// 忽略
"build": "node build/build.js"
},
"husky": {
"hooks": {
// 重点
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
}
}
这段配置告诉了 git hooks,当我们在当前项目中执行 git commit -m '测试提交' 时将触发 commit-msg 事件钩子并通知 husky,从而执行 commitlint -E HUSKY_GIT_PARAMS 命令,也就是我们刚开始安装的./node_modules/.bin/commitlint,它将读取 commitlint.config.js 配置规则并对我们刚刚提交的测试提交这串文字进行校验,若校验不通过,则在终端输出错误,commit 终止。
# 提交规范
commitlint 推荐我们使用 config-conventional 配置去写 commit
- 提交格式**(注意冒号后面有空格)**
git commit -m <type>[optional scope]: <description> type :用于表明我们这次提交的改动类型,是新增了功能?还是修改了测试代码?又或者是更新了文档?
optional scope:一个可选的修改范围。用于标识此次提交主要涉及到代码中哪个模块。
description:一句话描述此次提交的主要内容,做到言简意赅。
- 常用的 type 类型
类型 | 描述 |
---|---|
build | 编译相关的修改,例如发布版本、对项目构建或者依赖的改动 |
chore | 其他修改, 比如改变构建流程、或者增加依赖库、工具等 |
ci | 持续集成修改 |
docs | 文档修改 |
feat | 新特性、新功能 |
fix | 修改 bug |
perf | 优化相关,比如提升性能、体验 |
refactor | 代码重构 |
revert | 回滚到上一个版本 |
style | 代码格式修改, 注意不是 css 修改 |
test | 测试用例修改 |
- 例子
git commit -m 'fix(account): 修复xxx的bug'
git commit -m 'refactor: 重构整个项目'
# 原理
简单阅读了一遍 husky 和 commitlint 的源码,大概的执行过程是这样的,如图所示:
如果上面这张图看不太懂,这没关系,但你至少要看懂下面这张图: