六、Git提交规范的工具——commitlint

3,231 阅读5分钟

1. 介绍

  • commitlint 的作用:检测 git 提交的 message 是否符合规范

2. 安装

  • 核心依赖:@commitlint/cli
    • 该依赖为 commitlint 的命令行工具
  • 配置依赖:
    • commitlint 提供了多个配置依赖,可根据自己的实际需要去选择
    • 官网提供的一个配置依赖:@commitlint/config-conventional

3. 配置

3.1 配置文件

  • commitlint 支持的配置文件格式:
    • commitlint.config.js
    • .commitlintrc.js
    • .commitlintrc
    • .commitlintrc.json
    • .commitlintrc.yml
    • commitlint

3.2 配置项

  • 以 JS 格式为例
    • extends: 继承的配置集,接收一个数组作为参数,这个参数只需要配置依赖的名称

      • 第三方配置依赖插件
        • 例如 commitlint-config-example ,只需要添加配置项 extends: ["example"] 即可
      • 项目内的一个 js 文件
        • 例如 example.js 文件,只需他覅安家配置项 extends: ['./example'] 即可,不需要写扩展名
      • 带命名空间的第三方依赖插件
        • 例如上文提到的 @commitlint/config-conventional,需要添加配置项 extends: ['@commitlint/config-conventional'] 此时需要填写完整的包名
    • parserPreset: 指定解析加载器的名称,相关的依赖必须是已经安装的

    • formatter: 指定规范化的插件名称,相关的依赖必须是已经安装的

    • rules: 一个对象,每一个 key/value 对就是一条配置规则,这里的规则将会覆盖 extends 里指定的插件里的规则

    • ignores: 一个数组,数组里的每一个元素是一个函数,如果返回函数返回了 truecommitlint 就会忽略指定的 message

    • defaultIgnores: 布尔值,默认为 true,是否让 commitlint 使用默认的 ignore 规则

    • helpUrl: 失败时显示的自定义 URL

    • prompt: 一个对象,表示自定义的提示配置

      • 官方文档里给出的示例如下:

        {
          prompt: {
            messages: {},
            questions: {
              type: {
                description: 'please input type:',
              },
            },
          },
        }
        
        

3.3 Rules

  • 每一条规则的值都是一个元组数组,或是同步/异步返回一个元组数组的函数

  • 规则元组数组的第一个元素表示错误等级 (level),取值为 0 | 1 | 2

    • 0: 禁用这条规则
    • 1: 触发这条规则时 warning 提示
    • 2: 触发这条规则时 error 提示
  • 规则元组数组的第二个元素表示触发方式,取值为 always | never

    • always: 违背这条规则时,则根据 (level) 进行提示
      • 例如:{ body-full-stop: [2, "always", "stop"] } 这条规则的含义是,如果提交的 body 没有以 stop 结尾,则 error 提示
    • never: 反转这条规则,即满足这条规则时,则根据 (level) 进行提示
      • 例如:{ body-full-stop: [2, "never", "stop"] } 这条规则的含义是,如果提交的 body 以 stop 结尾了,则 error 提示
  • 规则元组数组的第三个元素表示这条规则允许的值,具体视每条规则而定

  • 支持的规则

    规则描述默认触发方式取值默认值
    body-full-stopbody 以指定的内容结尾never自定义任意字符串.
    body-leading-blankbody 和 type 之间是否换行always
    body-emptybody 是否允许为空never
    body-max-lengthbody 允许的最大字符长度always非负整数Infinity
    body-max-line-lengthbody 允许的最大行数always非负整数Infinity
    body-min-lengthbody 允许的最小字符长度always非负整数0
    body-casebody 的英文单词允许的风格always[
    'lower-case', // default
    'upper-case', // UPPERCASE
    'camel-case', // camelCase
    'kebab-case', // kebab-case
    'pascal-case', // PascalCase
    'sentence-case', // Sentence case
    'snake-case', // snake_case
    'start-case' // Start Case
    ]
    'lower-case'
    footer-leading-blankfooter 和 body 之间是否换行always
    footer-emptyfooter 是否允许为空never
    footer-max-lengthfooter 允许的最大字符长度always非负整数Infinity
    footer-max-line-lengthfooter 允许的最大行数always非负整数Infinity
    footer-min-lengthfooter 允许的最小字符长度always非负整数0
    header-caseheader 的英文单词允许的风格alwaysbody-case 的取值相同'lower-case'
    header-full-stopheader 以指定的内容结尾never自定义任意字符串.
    header-max-lengthheader 允许的最大字符长度always非负整数Infinity
    header-min-lengthheader 允许的最小字符长度always非负整数0
    references-emptyreferences 是否允许为空never
    scope-enumscope 只允许在列出的枚举值中always自定义枚举的数组[]
    scope-casescope 的英文单词允许的风格alwaysbody-case 的取值相同'lower-case'
    scope-emptyscope 是否允许为空never
    scope-max-lengthscope 允许的最大字符长度always非负整数Infinity
    scope-min-lengthscope 允许的最小字符长度always非负整数0
    subject-casesubject 的英文单词允许的风格alwaysbody-case 的取值相同[
    'sentence-case',
    'start-case',
    'pascal-case',
    'upper-case'
    ]
    subject-emptysubject 是否允许为空never
    subject-full-stopsubject 以指定的内容结尾never自定义任意字符串.
    subject-max-lengthsubject 允许的最大字符长度always非负整数Infinity
    subject-min-lengthsubject 允许的最小字符长度always非负整数0
    subject-exclamation-marksubject 是否在 subject 的 : 前加 !never
    type-enumtype 只允许为枚举列出的值always自定义的枚举数组[
    'feat',
    'fix',
    'docs',
    'style',
    'refactor',
    'test',
    'revert'
    ]
    type-casetype 的英文单词允许的风格body-case 的取值相同'lower-case'
    type-emptytype 是否允许为空never
    type-max-lengthtype 允许的最大字符长度always非负整数Infinity
    type-min-lengthtype 允许的最小字符长度always非负整数0
    signed-off-bymessage 中必须包含的字符always自定义字符串'Signed-off-by:'
    trailer-existsmessage 必须以指定的字符结尾always自定义字符串'Signed-off-by:'

附:相关资源

Sherry Standard Commitlint

根据我自己的开发习惯,我封装了一个自己的 Commitlint 配置——@sherry-standard/commitlint——有了这个包之后,我只需要在项目里安装 Commitlint 和这个包,再在 package.json 里增加如下配置,就可以快乐地使用 Commitlint 了。

{
  // 其他配置
  "commitlint": {
    "extends": [
      "@sherry-standard/commitlint"
    ]
  },
  // 其他配置
}

配置示例

module.exports = {
  extends: ["@commitlint/config-conventional"],
  rules: {
    // type 不允许为空
    "type-empty": [
      2, // 触发这条规则时 error 提示
      "never", // 满足这条规则时,则根据(level=2)进行 error 提示
    ],
    // type 允许的类型
    "type-enum": [
      2, // 触发这条规则时 error 提示
      "always", // 违背这条规则时,则根据 (level) 进行提示
      [
        "feat", // 新功能
        "fix", // bug 修复
        "docs", // 文档更新
        "style", // 样式调整
        "refactor", // 代码重构
        "test", // 编写测试用例
        "revert", // 代码回滚
        "chore", // 项目配置更新
        "perf", // 性能优化
      ],
    ],
    // body 至少包含4个字符
    "body-min-length": [2, "always", 4],
  },
};