hook
hook,钩子:即某个时期或事件之前、之后执行和一些操作或脚本。与我们常说的中间件很相似。
git-hooks
git有很多hook,每当我们git init
初始化一个git仓库时,都会创建一个.git的隐藏文件夹,git的hook就放在.git/hooks下。hooks以.sample为后缀的是示例文件。git-hooks有客户端hooks和服务端的hooks。
这里介绍客户端会用到的hooks
- pre-commit: 钩子在键入提交信息前运行。 它用于检查即将提交的快照,例如,检查是否有所遗漏,确保测试运行,以及核查代码。
- commit-msg: 钩子在启动提交信息编辑器之前,默认信息被创建之后运行。 它允许你编辑提交者所看到的默认信息。
git仓库根目录的隐藏文件夹.git里的git-hooks是不被git管理的,只存在于本地。所以无法让仓库中所有成员使用同样的hooks。这时候就需要通过工具库来使用git-hooks,就是husky。
husky
- 安装 husky
pnpm add --save-dev husky
- 添加 git hooks
pnpm exec husky init
init命令简化了在项目中设置husky的过程。它在.husty/中创建了一个预提交脚本,并在package.json中更新了prepare脚本
- 添加新钩子
# echo方式,是适用于linux/mac的。
echo "command" > .husky/pre-[hook_name]
#window
node --eval "fs.writeFileSync('./.husky/.pre-[hook-name]','commoand')"
这样就可以在hooh_name钩子期间触发command命令
接下来我们就可以借助commitlint
校验commit信息。借助lint-staged
来实现对暂存区的代码进行风格校验和格式化。
commitlint
commitlint是对commit信息校验的一款npm包。
- 安装
pnpm i @commitlint/cli @commitlint/config-conventional -D
- 添加git-hook
#linux/mac
echo 'npx --no-install commitlint --edit "$1"' > .husky/commit-msg
#window
node --eval "fs.writeFileSync('./.husky/commit-msg','npx --no-install commitlint --edit "$1"')"
现在我们只是增加了对commit message的校验,但是在使用 Git 过程中,填写 commit message其实是比较麻烦的。如果没有良好的 commit message 规范,commit历史就会很乱。这时就需要 commitizen
来协助开发者填写 commit 信息。
commitizen
commitizen是基于 Node.js 开发的 git commit 命令行工具,用来生成标准化的commit-message。commitizen 本身只提供命令行交互框架以及一些 git 命令的执行,实际的规则则需要通过适配器来定义,commitizen 留有对应的适配器接口。市面上有很多适配器,比如: cz-conventional-changelog
、cz-git
。常见适配器生产commit-message模板
<type>(<scope>): <subject>
<空行>
<body>
<空行>
<footer>
- 安装 commitizen
pnpm install commitizen -D
- 初始化,参数含义:使用cz-git适配器初始化commitizen,并用pnpm安装依赖。
npx commitizen init cz-git --save-dev --save-exact --pnpm
commitizen init 做了什么
1. 安装 `cz-git` 适配器 npm 模块
2. 将其保存到 package.json 的 devDependencies 中
3. 添加配置到 package.json 中 如下:
"config": {
"commitizen": {
"path": "./node_modules/cz-git"
}
}
- 新建 commitlint.config.js 文件:(
对提交信息做格式检验的
)
/*
* @Author: daiend
* @Date: 2024-02-29 10:48:00
* @Last Modified by: daiend
* @Last Modified time: 2024-02-29 10:48:00
* @Description: 代码提交message规范
*/
export default {
ignores: [(commit) => commit === 'init'],
extends: ['@commitlint/config-conventional'],
rules: {
'body-leading-blank': [2, 'always'],
'footer-leading-blank': [1, 'always'],
'header-max-length': [2, 'always', 108],
'subject-empty': [2, 'never'],
'type-empty': [2, 'never'],
'subject-case': [0],
'type-enum': [2, 'always', ['feat', 'fix', 'docs', 'style', 'refactor', 'perf', 'test', 'build', 'ci', 'chore', 'revert', 'wip', 'workflow', 'types', 'release']],
},
prompt: {
messages: {
type: '选择你要提交的类型 :',
scope: '选择一个提交范围(可选):',
customScope: '请输入自定义的提交范围 :',
subject: '填写简短精炼的变更描述 :\n',
body: '填写更加详细的变更描述(可选)。使用 "|" 换行 :\n',
breaking: '列举非兼容性重大的变更(可选)。使用 "|" 换行 :\n',
footerPrefixsSelect: '选择关联issue前缀(可选):',
customFooterPrefixs: '输入自定义issue前缀 :',
footer: '列举关联issue (可选) 例如: #31, #I3244 :\n',
confirmCommit: '是否提交或修改commit ?',
},
types: [
{ value: 'feat: 特性', name: '特性: ✨ 新增功能', emoji: '✨' },
{ value: 'fix: 修复', name: '修复: 🧩 修复缺陷', emoji: '🧩' },
{ value: 'docs: 文档', name: '文档: 📚 文档变更', emoji: '📚' },
{ value: 'style: 格式', name: '格式: 🎨 代码格式(不影响功能,例如空格、分号等格式修正)', emoji: '🎨' },
{ value: 'refactor: 重构', name: '重构: ♻️ 代码重构(不包括 bug 修复、功能新增)', emoji: '♻️' },
{ value: 'perf: 性能', name: '性能: ⚡️ 性能优化', emoji: '⚡️' },
{ value: 'test: 测试', name: '测试: ✅ 添加疏漏测试或已有测试改动', emoji: '✅' },
{ value: 'chore: 杂务', name: '杂务: ☕ 零星工作(如升级 npm 包、修改配置等)', emoji: '☕' },
{ value: 'ci: 集成', name: '集成: 🛠️ 修改 CI 配置、脚本', emoji: '🛠️' },
{ value: 'revert: 回退', name: '回退: ⏪️ 回滚 commit', emoji: '⏪️' },
{ value: 'build: 打包', name: '打包: 📦️ 项目打包发布', emoji: '📦️' },
],
useEmoji: true,
},
};
- 配置 package.json 命令
"scripts": {
"commit": "git status && git add -A && git-cz"
}
运行pnpm run commit
以触发git-hook规范commit message
lint-staged
一般情况下 lint-staged
搭配着 Husky
一起使用。需要保证lint-staged
会在 pre-commit hook 中被运行。在使用lint-staged校验代码和代码风格时这里使用的是prettier
和eslint
。
- 安装
pnpm install lint-staged --save-dev
- 添加 git hooks
#mac/linux
echo "npx lint-staged" > .husky/pre-commit
#window
node --eval "fs.writeFileSync('.husky/pre-commit','npx lint-staged\n')"
- 配置
形式一:package.json 中添加一个 lint-staged
项。
"lint-staged": {
"*.{js,jsx,ts,tsx}": ["eslint --fix", "prettier --write"],
"*.json": ["prettier --write"],
"*.vue": ["eslint --fix', 'prettier --write', 'stylelint --fix"],
"*.{scss,css,sass,less,html}": ["stylelint --fix ", "prettier --write"],
"*.md": ["prettier --write"]
}
形式二:根目录添加一个 .lintstagedrc.json
文件。
//.lintstagedrc.json
{
"*.{js,jsx,ts,tsx}": ["eslint --fix", "prettier --write"],
"*.json": ["prettier --write"],
"*.vue": ["eslint --fix", "prettier --write"],
"*.{scss,css,sass,less,html}": [ "prettier --write"],
"*.md": ["prettier --write"]
}
之后每次的pre-commit钩子触发都会执行代码校验和代码格式化。