node项目配置 husky + commitizen + cz-customizable 规范git commit message

792 阅读4分钟

背景

目前开发中,git commit message书写不规范是个很常见的问题, 所以可以引入commitizen来辅助生成提交信息,减少书写成本,提高规范性。

配置步骤

1.安装依赖

如标题所示,需要的依赖包共有三个:huskycommitizencz-customizable,具体每个包的详细信息就不再介绍了,不了解且有兴趣的同学可以自行去npm上查看README文件。

# yarn
yarn add husky commitizen cz-cuztomizable -D

# npm
npm i husky commitizen cz-cuztomizable -D

#pnpm
pnpm i husky commitizen cz-cuztomizable -D

2.增加自定义cz配置

cz-customizable提供了自定义配置的能力,在需要执行cz命令的文件夹 (一般为根目录,特殊配置的monorepo项目根据实际情况来看) 下创建.cz-config.js文件,并添加自定义配置,完整配置见README

  • cz-config.js
// .cz-config.js
// 个人demo,经由ChatGPT润色的中文版

module.exports = {
  // 这里配置type的option值,可自行调整顺序或修改文案
  types: [
    {
      value: 'feat',
      name: 'feat(新功能): 向现有功能添加新功能或改进'
    },
    {
      value: 'fix',
      name: 'fix(修复): 修复代码库中的bug或者issues'
    },
    {
      value: 'chore',
      name: 'chore(任务): 构建/工程依赖/工具/文档更新/格式化'
    },
    {
      value: 'docs',
      name: 'docs(文档): 为代码库更新文档'
    },
    {
      value: 'style',
      name: 'style(样式): 改善代码库的格式或风格, 修改页面样式'
    },
    {
      value: 'refactor',
      name: 'refactor(重构): 对代码库的结构或组织进行重组或改进'
    },
    {
      value: 'perf',
      name: 'perf(性能): 代码库性能优化'
    },
    {
      value: 'init',
      name: 'init(初始化): 项目初始化'
    },
    {
      value: 'test',
      name: 'test(测试): 自动化测试'
    },
    {
      value: 'revert',
      name: 'revert(回退): 撤销之前某个提交'
    },
    {
      value: 'build',
      name: 'build(构建): 重构系统编译配置'
    }
  ],
  // 每一步的提示信息
  messages: {
    type: '请选择提交类型',
    scope: '请选择文件修改范围',
    subject: '请输入commit标题(必填)',
    body: '请输入commit描述, 可通过&换行(选填)',
    // breaking: '列出任何BREAKING CHANGES(破坏性修改)(可选)',
    // footer: '请输入要关闭的issue(可选)',
    confirmCommit: '确定提交此 commit 吗?'
  },
  // 配置scope可选项,mono项目可按子项目维度划分,非mono项目可按功能or业务模块划分
  scopes: ['global', 'scope1', 'scope2'],
  // commit描述的换行符
  breaklineChar: '&',
  skipQuestions: ['breaking', 'footer'],
  // 标题首字母大写
  upperCaseSubject: true,
  // 标题必填
  requiredSubject: true
};

此配置文件可同时被IDE的cz插件使用,如VsCode的Visual Studio Code Commitizen Support插件,如果想让插件使用此配置,配置文件需要位于项目根目录下

3. 配置huksy,通过git hook触发cz

package.json中增加husky相关配置

...
"husky": {
    "hooks": {
      ...
      "prepare-commit-msg": "sh ./bash/prepare-commit-msg.sh"
    }
  }
...

4. 增加相关脚本

  • check-msg
# ./bash/check-msg.sh

#!/bin/bash

# 该文件用来判断当前是不是 git merge 状态,如果是的话,本地 .git下 会存在 MERGE_MSG 文件
# 尝试读取该文件内容,如果是 Merge branch 开头,我们认为此时就是 merge 状态
# 在该状态下,跳过 lint-staged 和 commitizen 两步,因为检查没有意义
# 补充rebase的判断,如果处于rebase状态,也跳过相关操作

set -e
# merge 信息存放位置
check_file=$(pwd)"/.git/MERGE_MSG";
#rebase目录
check_rebase_apply=$(pwd)"/.git/rebase-apply";
check_rebase_merge=$(pwd)"/.git/rebase-merge";

# 判断文件是否存在
if [ -f "$check_file" ]; then
  # 读取 merge 信息
  mergeMsg=`cat '.git/MERGE_MSG'`;
  # 如果是以 Merge branch 开头,返回2
  if [[ $mergeMsg =~ ^Merge.*branch ]]; then
    exit 2;
  # 其他特殊情况解决冲突,正常不会走到此if分支
  elif [[ $mergeMsg = *"Conflict"* ]]; then
    exit 2;
  fi;
fi;

# reabase过程返回2
if [ -d "$check_rebase_apply" ] || [ -d "$check_rebase_merge" ]; then
  exit 2;
fi; 

# 非Merge状态也非rebase状态
exit 1;
  • prepare-commit-msg
# ./bash/prepare-commit-msg.sh

#!/bin/bash

# calculate bin dir
# merge 信息, 通过merge&rebase生成的commit不再执行git-cz
sh -e $(pwd)"/bash/check-msg.sh";

if [ "$?" = "1" ]; then
  # 打开 commitizen 交互界面,辅助生成 commit 信息
  INFRA_DIR_NAME=$(dirname $(dirname "$0"))
  cd $INFRA_DIR_NAME
  # 打开新的终端运行cz,并标识是由hook触发的
  exec < /dev/tty && npx cz --hook || true
fi;

4. 愉快的使用

这时候可以直接正常执行git commit指令,hook会自动触发cz, 保证每位同学都可以享受到插件带来的效果。

image.png

image.png

总结

  • 优势
    • 如果直接通过cz指令去触发,那么会首先打开cz交互页面,生成相关信息后再去执行pre-commit配置的lint相关检测,如果检测不通过可能会导致本次信息白写的情况,但是通过hook执行的话就可以先执行lint,通过之后再触发cz
    • 部分设备可能执行cz会报错(获取到了错误的git仓库路径),通过排除变量发现大概率是git版本问题,版本过低执行会出问题,遇到这情况可以尝试升级git版本。另外,任何地方抛错都不会阻塞本次提交,只会直接跳到最后一步,就是安装插件以及配置hook前的状态
    • 不会被--no-verify跳过
    • 可以直接ctrl + c跳过(cz执行过程中)
    • 如果直接使用git commit -m 'xxxx'来提交的话,触发hook后新生成的message会把-m里面的覆盖掉
    • 使用IDE里的git插件提交代码的话,因为无法获取到终端,会直接报错跳过,不影响正常提交 (VsCode可以配合Visual Studio Code Commitizen Support插件使用,其余IDE可自行搜索cz相关插件)