Skip to content

使用 husky 让代码提交优雅规范

日常工作中,几乎每个项目都是由多个人进行维护,每个人的代码书写习惯和风格又不尽相同,在这种情况下,如果没有统一的规范,你就会发现提交到代码仓库的代码格式五花八门,并且 commit log 也是乱七八糟,更严重点可能有的小伙伴在提交代码的时候为了省事 commit message 直接就是两个点点,总之,可能就是怎么省事怎么来。最终导致的结果就是,当你某一天需要 cherry-pick 某个 commit 到另外的分支的时,看着 commmit log 一脸懵逼。所以,规范和约束在多人协作下,就显得尤为重要

githooks

类似于前端框架中的生命周期钩子,git在某些特定事件发生前或后也会有某些执行特定功能的钩子,githooks 就是在 git 执行特定事件(如commit、push、receive等)时触发运行的脚本。

githooks 保存在 .git 文件夹中

具体钩子如下表所示:

Git Hook执行时机说明
applypatch-msggit am 执行前默认情况下,如果 commit-msg 启用的话,applpatch-msg 钩子在启用时会运行commit-msg 钩子
pre-applypatcgit am 执行前默认的 pre-applypatch 钩子在启用时运行pre-commit 钩子(如果后者已启用)
post-applypatchgit am 执行后这个钩子主要用于通知,不能影响git-am的结果
pre-commitgit commit 执行前可以使用 git commit –no verify 命令绕过该钩子
pre-merge-commitgit merge 执行前可以使用 git merge –no verify 命令绕过该钩子
prepare-commit-msggit commit执行之后,编辑器打开之前 
commit-msggit commit 执行前可以使用 git commit –no verify 命令绕过该钩子
post-commitgit commit 执行后不影响git commit的结果
pre-rebasegit rebase执行前 
post-checkoutgit checkout 或 git switch执行后如果不使用 –no-checkout 参数,则在 git clone 之后也会执行
post-mergegit merge 执行后在执行git pull 时也会被调用
pre-push git push 执行前
pre-receivegit receive pack 执行前 
update  
proc-receive  
post-receivegit receive pack 执行前不影响 git receive pack 的执行结果
post-update当git receive pack对 git push 作出反应并更新仓库中的引用时 
reference-transaction  
push-to-checkout当git receive pack对 git push 作出反应并更新仓库中的引用时,以及当推送试图更新当前被签出的分支且 receive.denyCurrentBranch配置被updateInstead时 
pre-auto-gcgit gc –auto 执行前 
post-rewrite执行 git commit –amend 或 git rebase 时 
sendemail-validategit send-email 执行前 
fsmonitor-watchman配置 core.fsmonitor 被设置为  
p4-changelistgit-p4 submit 执行并编辑完changelist message 之后可以使用 git-p4 submit –no-verify绕过该钩子
p4-prepare-changelistgit-p4 submit 执行后,编辑器启动前可以使用 git-p4 submit –no-verify绕过该钩子
p4-post-changelistgit-p4 submit 执行后 
p4-pre-submitgit-p4 submit 执行前可以使用 git-p4 submit –no-verify绕过该钩子
post-index-change索引被写入 read-cache.c do_write_locked_index后 

husky

husky 是一个让配置 git 钩子变得更简单的工具。支持所有的 git 钩子

安装

# pnpm
$ pnpm install husky -D

prepare 生命周期中保障 husky 的自动安装, 保障安装之后自动启用钩子

# npm
$ npm pkg set scripts.prepare="husky install"

执行完上一步的命令之后可以在 package.json 文件的 scripts 配置项中看到如下代码, 当然代码也可以手动添加

json
{
  "scripts": {
    "prepare": "husky install"
  }
}

运行 pnpm prepare 执行 husky 安装

如果在未初始化 git 的目录中运行则会出现如下错误, 这里是将 husky 自动加入 git 钩子

创建钩子,比如我们创建一个 commit-msg 钩子, 这里的意思是在 git commit-msg 的时候运行 commitlint 校验工具

$ pnpm husky add .husky/commit-msg 'npx commitlint --edit "$1"'

lint-staged

lint-staged/lint-staged 是一个在git暂存区上运行 linters 的工具

Run linters against staged git files and don’t let 💩 slip into your code base

它将根据 package.json 依赖项中的代码质量工具来安装和配置 husky 和 lint-staged ,因此请确保在此之前安装并配置所有代码质量工具,比如 prettier 和 eslint

安装

shell
$ pnpm add lint-staged -D

执行 npx lint-staged --help 命令可以看到相关的所有参数如下:

$ npx lint-staged --help
Usage: lint-staged [options]

Options:
  -V, --version                      输出版本号
  --allow-empty                      当任务撤消所有分阶段的更改时允许空提交(默认值:false)
  -c, --config [path]                配置文件的路径
  -d, --debug                        打印其他调试信息(默认值:false)
  -p, --concurrent <parallel tasks>  要同时运行的任务数,或者为false则要连续运行任务(默认值:true)
  -q, --quiet                        自己的控制台输出(默认值:false)
  -r, --relative                     将相对文件路径传递给任务(默认值:false)
  -x, --shell                        跳过任务解析以更好地支持shell(默认值:false)
  -h, --help                         输出用法信息

--allow-empty :使用此参数允许创建空的git提交。默认情况下,当 LITER 任务撤消所有阶段性的更改时,LITET 阶段将抛出一个错误,并中止提交。

git commit 提交规范

通常使用 Google AnguarJS 规范的要求。 格式要求:

<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>
  • <type> 代表某次提交的类型,比如是修复一个 bug 或是增加一个 feature,具体类型如下:
类型说明
feat新增feature
fix修复bug
docs仅仅修改了文档,比如README, CHANGELOG, CONTRIBUTE等等;
style仅仅修改了空格、格式缩进、逗号等等,不改变代码逻辑;
refactor代码重构,没有加新功能或者修复bug
perf优化相关,比如提升性能、体验
test测试用例,包括单元测试、集成测试等
chore改变构建流程、或者增加依赖库、工具等
revert回滚到上一个版本
  • scope :说明 commit 影响的范围。scope 依据项目而定,例如在业务项目中可以依据菜单或者功能模块划分,如果是组件库开发,则可以依据组件划分
  • subject : 是 commit 的简短描述
  • body : 提交代码的详细描述
  • footer : 如果代码的提交是不兼容变更或关闭缺陷,则 footer 必需,否则可以省略

eslint & stylelint

安装 eslint

安装 eslint 和项目需要的 eslint 配置

shell
# 基础的 eslint 配置
$ pnpm add -D eslint

# 项目中规则需要的 eslint 配置(按需加载)
$ pnpm add -D eslint-config-airbnb-base eslint-plugin-import eslint-plugin-simple-import-sort eslint-plugin-vue eslint-plugin-vue-scoped-css

# 基础的 prettier
$ pnpm add -D prettier

# 基于项目配置文件的 prettier
$ pnpm add -D eslint-config-prettier eslint-plugin-prettier

添加 linter 命令

shell
# eslint
$ npm pkg set scripts.eslint="eslint --ext .vue,.js,.jsx,.ts,.tsx ./ --max-warnings 0"
$ npm pkg set scripts.eslint:fix="eslint --ext .vue,.js,jsx,.ts,.tsx ./ --max-warnings 0 --fix"

安装 stylelint

shell
# 基础的 stylelint
$ pnpm add stylelint

# 项目中需要的 stylelint 规则
$ pnpm add -D stylelint-config-standard stylelint-order

添加 stylelint 命令

shell
# stylelint
$ npm pkg set scripts.stylelint="stylelint src/**/*.{html,vue,sass,less}"
$ npm pkg set scripts.stylelint:fix="stylelint --fix src/**/*.{html,vue,css,sass,less}"

配置 lint-staged 在项目中的验证

husky 准备好之后,我们接着来检查代码的依赖

package.json 文件下添加如下代码, 根据需要来添加 eslint 或者 stylelint 的要求

json
{
  "lint-staged": {
    "src/**/*.{js,jsx,ts,tsx,json}": [
			"prettier --write", 
			"npm run eslint:fix"
		],
    "*.{html,vue,css,sass,less}": [
			"npm run stylelint:fix"
		]
  }
}

安装提交约定

安装 commitlint 相关依赖, 用来帮助我们在多人开发时,遵守 git 提交约定

shell
$ pnpm add @commitlint/cli @commitlint/config-conventional -D

在根目录创建 commitlint.config.js 文件,其内容如下所示:

javascript
module.exports = {
  extends: ["@commitlint/config-conventional"],
  // 以下是我们自定义的规则
  rules: {
    "type-enum": [
      2,
      "always",
      [
        "build", // 构建相关
        "chore", // 辅助工具的变动
        "ci", // 自动化构建
        "docs", // 文档(documentation)
        "bug", // 此项特别针对bug号,用于向测试反馈bug列表的bug修改情况
        "feat", // 新功能(feature)
        "fix", // 修补bug
        "style", // 格式(不影响代码运行的变动)
        "refactor", // 重构(即不是新增功能,也不是修改bug的代码变动)
        "test", // 增加测试
        "revert", // feat(pencil): add ‘graphiteWidth’ option (撤销之前的commit)
        "types", // 定义规则
      ],
    ],
  },
};

至此,准备好我们需要的依赖包之后,我们开始添加钩子

提交约定钩子

shell
$ pnpm husky add .husky/commit-msg 'npx commitlint --edit "$1"'

执行后,会看到在根目录的 .husky 文件夹下多了一个 commit-msg 文件,其内容如下:

bash
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npx commitlint --edit "$1"

待提交区代码 lint

shell
$ pnpm husky add .husky/pre-commit 'npx lint-staged --allow-empty "$1"'

执行之后,会看到在根目录的 .husky 文件夹下多了一个 pre-commit 文件,其内容如下:

bash
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npx lint-staged --allow-empty "$1"

接下来,就是检验配置的时候了:当我们按照 commit 规范正确提交时,可以在控制台看到如下输出

当我们不按照配置的规范来提交commit时,就会发现如下报错,并阻止你提交代码

至此,配置完美收官

参考

2023年11月24日

  • 命令更新为 pnpm
  • 移除过时的 npm set-script 命令
  • 加入stylelint 支持 css 样式

说明

创建时间: 2023-01-15 00:29:00 , 最后编辑于 2023-11-27 09:58:00