在git提交规范中使用husky与lint-staged

1,736 阅读7分钟

在前端项目开发中,规范git提交信息,也是经常使用的手段,本文将介绍husky与lint-staged等工具,使用好它们,将有助于我们在项目开发中的git规范和团队协作。

husky

Husky 是一款管理 git hooks 的工具,可以让我们更方便的管理 git hooks 脚本。
它将在我们提交代码时触发不同的钩子,执行不同脚本,帮忙我们自动化的处理一些任务,比如执行 eslint 命令等。

首先,安装husky:

npm install husky -D

然后,在 package.json 文件的 scripts 中配置自动安装脚本:

"prepare": "husky install"

当设置了该配置脚本后,在我们执行 npm install 命令操作时,会自动执行 npm run prepare 命令,即会执行 husky install 命令,并在项目的根目录下生成 .husky 目录,如下图所示:

husky目录.png

.husky 目录下会自动生成两个文件,其中脚本文件 husky.sh 表示 husky 的初始化基础配置。

除此外,我们当然也可以直接执行 prepare 命令,同样有效:

npm run prepare

自定义配置目录

.husky 目录是默认生成的,当然我们也可以自定义husky配置的文件目录,只需要在命令中加入参数即可,如下所示:

husky install gitHooks/husky

这样,就会在项目根目录下,生成 gitHooks 目录和 husky 子目录,而对应的初始化配置文件也会自动生成。

npm生命周期

上面提到的执行 npm install 命令操作会自动执行 npm run prepare 命令,是源自npm的生命周期钩子。

preparenpm 脚本命令操作的生命周期中的一个阶段,当执行 install 的时候会触发该操作。
执行 install 命令时,将按顺序依次执行对应的命令:

  • npm 6.x:preinstall -> install -> postinstall -> prepublish -> prepare
  • npm 7+:preinstall -> install -> postinstall -> prepublish -> preprepare -> prepare -> postprepare

知晓具体的执行顺序后,我们就可以在不通过的阶段加入我们想要的操作,比如上面的自动安装husky工具。

比如,我们也可以在scripts中添加钩子,统一项目的包管理工具:

"preinstall": "npx only-allow pnpm",

通过以上命令,将项目的包安装工具指定为 pnpm,如果使用 npmyarn 来执行 install 则报错,无法安装三方包。

设置git hooks

husky安装完成,并配置好脚本后,我们就可以进行 git hooks 的设置。
git hooks 让我们能够在git操作的特定命令发生时自动执行自定义的脚本,用来完成一些额外的事情。
而我们在git提交信息的规范中,一般常用的两个阶段是:pre-commitcommit-msg

  • pre-commit:在代码提交之前执行。可处理代码格式规范等。
  • commit-msg:处理代码提交的message信息。

除此以外,git hooks还有多个阶段,可以在需要的时候启用,比如以下这些:

pre-receive:从本地版本完成一个推送后
prepare-commit-msg:信息准备完成后但编辑尚未启动
pre-push:push 之前执行
post-update:在工作区更新完成后执行
pre-rebase:在rebase操作之前执行

pre-commit

上面介绍中,提到husky工具会在根目录下生成 .husky 目录,保存有husky的基本配置。要想配置 git hooks,还得在这个目录下进行操作,可以采取下面两种方式。

  • 第一种,我们可以直接在 .husky 目录下新建文件:pre-commit,注意无后缀名。然后给该文件添加以下内容:
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

npx eslint src

其中,npx eslint src 是需要在git提交前执行的命令,也可以换成类似 npm run lintscripts 脚本。

  • 第二种,或者使用脚本命令生成该文件,执行以下脚本:
npx husky add .husky/pre-commit "npx eslint src"

该脚本执行后,将在 .husky 目录下自动生成 pre-commit 文件,并且写入对应的脚本命令:npx eslint src,内容与上面的第一种方式一样。

完成以上操作后,当我们执行 git commit 命令时,就会自动执行eslint命令。除了eslint,我们也可以配置其他诸如 stylelintprettier 等等。

commit-msg

对git提交信息中 message 的规范,也是我们在项目开发中必不可少的一环,这块内容对团队协作、版本日志等都能带来帮助。
提交 message 的规范有多种约定式的规范,如 Conventional Commits specification,但只靠规范约定很显然不能保证规范完整正确的被执行,所以需要辅助工具来帮助我们处理,比如 commitlint

commitlint

commitlint 是当前使用最广泛的git提交规范检验工具,能够较好的帮助我们在项目开发中,对提交信息的 message 规范进行校验。

首先,我们需要安装两个依赖包:

npm install @commitlint/cli -D
npm install @commitlint/config-conventional -D

其中:

  • @commitlint/config-conventional 是基于 conventional commits 规范的配置文件。
  • @commitlint/cli 是 commitlint 工具的核心。
配置commitlint

然后,增加 .commitlintrc.js 配置文件:

也可以在 package.json 文件中增加 commitlint 字段的配置。

module.exports = {
  extends: ['@commitlint/config-conventional'],
  rules: {
    'type-enum': [
      2,
      'always',
      [
        'feat', // 新功能(feature)
        'fix', // 修复bug
        'docs', // 修改文档
        'style', // 修改代码格式,不影响代码逻辑
        'refactor', // 代码重构,理论上不影响功能逻辑
        'test', // 修改测试用例
        'build', // 构建或其他工具的变动(如webpack)
        'revert', // 还原以前的提交
        'merge', // 分支代码合并
      ],
    ],
  },
};

以上就是一个基础的命令配置,主要定义了 type 的内容,提交 messagetype 需要遵循以上配置的。

gitCommit Message 包含三部分:HeaderBodyFooter
其中 Header 是必需的,在绝大部分的项目开发中,我们的git提交信息,应该只包含该部分。
Header 也包含三个部分:typescopesubject,其中 typesubject 是必需项。
type 代表提交信息的类型,上面配置文件里就主要规范了该类型。
subject 代表提交信息的说明描述内容。

设置commit-msg hook

接下来,配置 commit-msg hook,通过前面介绍的husky工具,我们直接在 .husky 目录下新建文件 commit-msg,内容如下:

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

npx --no-install commitlint --edit $1

也可以使用脚本命令执行,自动生成该文件和内容:

npx husky add .husky/commit-msg 'npx --no-install commitlint --edit $1'

如果不用 npx 命令,使用yarn也是可以的,yarn commitlint --edit $1

配置好hook文件后,就基本完成该操作,可以进行验证了。

验证git提交

下面,我们提交一个不符合规范的git信息:

git commit -m '测试一下'

这时候,就会提交失败,信息如下:

提交失败.png

上图所示,git提交失败,存在问题:typesubject 内容可能为空。
因为前文 commitlint 配置了 type 信息,我们提交时也需要加上 type 类型,并带上冒号,如以下命令,就能够正常提交:

git commit -m 'test: 测试一下'

上图中有一条:No staged files match any configured task.
这是我们已经设置了 lint-staged,但当前并没有代码文件被命中,才会出现这条提示。

lint-staged

在介绍 pre-commit 的时候,我们使用了 npx eslint src 命令来处理代码规范。
但它存在一个问题,就是每次git提交都会对整个项目src中的所有文件都进行检测,很多时候这是不需要的,最好的方法就是对新修改的代码进行检测。
lint-staged 工具就是基于此,只针对提交的代码文件进行检查处理。

安装 lint-staged:

npm install lint-staged -D

lint-staged 需要增加配置,一般可以使用两类方式。

  • 直接在package.json文件中增加内容,如下所示:
"lint-staged": {
  "*.{js,jsx,vue,ts}": [
    "eslint src"
  ]
}
  • 或者,增加配置文件,如 lintstagedrc.json,内容如下:
{
  "*.{js,jsx,vue,ts}": ["eslint src"]
}

配置好以后,可以修改pre-commit文件,添加以下脚本:

npx lint-staged

至此,则 lint-staged 就设置完成,当再次使用 git commit 提交代码的时候,就会先执行代码检查之类的动作,并且是增量代码检查

跳过 git hooks

如果我们想要跳过 commit 相关的hook,可以使用在脚本命令中加上 --no-verify 参数,如下所示:

git commit -m '跳过hook' --no-verify

这样,我们前面设置的检查,都将被跳过,直接完成代码提交动作。