Commitlint
使用 commitlint 配置和规则,根据 Conventional Commits 格式验证提交信息。
何时使用此技能
在以下场景使用此技能:
- 为仓库设置 commitlint
- 配置 commitlint 规则和可共享配置
- 将 commitlint 集成到预提交 hooks 或 CI/CD 管道中
- 从 commitlint 配置中提取规则,为提交信息生成生成 LLM 提示
- 以编程方式验证提交信息
- 排查 commitlint 配置或验证错误
- 理解 commitlint 规则语法和严重级别
- 检测仓库中的 commitlint 配置文件
核心功能
配置检测
Commitlint 使用 cosmiconfig 按以下优先级查找配置文件:
专用配置文件:
.commitlintrc
.commitlintrc.json
.commitlintrc.yaml
.commitlintrc.yml
.commitlintrc.js
.commitlintrc.cjs
.commitlintrc.mjs
.commitlintrc.ts
.commitlintrc.cts
commitlint.config.js
commitlint.config.cjs
commitlint.config.mjs
commitlint.config.ts
commitlint.config.cts
包文件:
package.json中的commitlint字段package.yaml(PNPM) 中的commitlint字段
配置格式
JavaScript ES Modules(推荐):
// commitlint.config.js 或 commitlint.config.mjs
export default {
extends: ['@commitlint/config-conventional'],
};
TypeScript:
// commitlint.config.ts
import type { UserConfig } from '@commitlint/types';
import { RuleConfigSeverity } from '@commitlint/types';
const config: UserConfig = {
extends: ['@commitlint/config-conventional'],
rules: {
'type-enum': [RuleConfigSeverity.Error, 'always', ['feat', 'fix', 'docs']],
},
};
export default config;
JSON:
{
"extends": ["@commitlint/config-conventional"]
}
YAML:
extends:
- "@commitlint/config-conventional"
规则配置
规则配置为数组:[级别, 适用性, 值]
严重级别:
| 级别 | 含义 | TypeScript 枚举 |
|---|---|---|
| 0 | 禁用 | RuleConfigSeverity.Disabled |
| 1 | 警告 | RuleConfigSeverity.Warning |
| 2 | 错误 | RuleConfigSeverity.Error |
适用性:
'always'- 规则必须匹配'never'- 规则不得匹配
示例规则:
rules: {
// 如果 type 不在枚举中,则报错
'type-enum': [2, 'always', ['feat', 'fix', 'docs', 'style', 'refactor', 'perf', 'test', 'build', 'ci', 'chore', 'revert']],
// 如果 type 为空,则报错
'type-empty': [2, 'never'],
// 如果 subject 为空,则报错
'subject-empty': [2, 'never'],
// 如果 header 超过 100 字符,则报错
'header-max-length': [2, 'always', 100],
// 如果 subject 以句点结尾,则报错
'subject-full-stop': [2, 'never', '.'],
// 如果 body 没有前导空行,则警告
'body-leading-blank': [1, 'always'],
}
常用配置
@commitlint/config-conventional
最广泛使用的可共享配置。默认错误级别的规则:
| 规则 | 配置 | 通过示例 | 失败示例 |
|---|---|---|---|
type-enum | ['build', 'chore', 'ci', 'docs', 'feat', 'fix', 'perf', 'refactor', 'revert', 'style', 'test'] | fix: message | foo: message |
type-case | 'lowerCase' | fix: message | FIX: message |
type-empty | never | fix: message | : message |
subject-case | never + ['sentence-case', 'start-case', 'pascal-case', 'upper-case'] | fix: some message | fix: Some Message |
subject-empty | never | fix: message | fix: |
subject-full-stop | never, '.' | fix: message | fix: message. |
header-max-length | 100 | 短 header | Header > 100 字符 |
body-leading-blank | always (警告) | body 前有空行 | 无空行 |
body-max-line-length | 100 | 行 <= 100 字符 | 行 > 100 字符 |
footer-leading-blank | always (警告) | footer 前有空行 | 无空行 |
footer-max-line-length | 100 | 行 <= 100 字符 | 行 > 100 字符 |
完整配置模式
// commitlint.config.js
export default {
// 扩展可共享配置(通过 node 解析)
extends: ['@commitlint/config-conventional'],
// 解析提交信息的解析器预设
parserPreset: 'conventional-changelog-atom',
// 输出格式化程序
formatter: '@commitlint/format',
// 自定义规则(覆盖继承的规则)
rules: {
'type-enum': [2, 'always', ['feat', 'fix', 'docs', 'style', 'refactor', 'test', 'chore']],
},
// 返回 true 以忽略特定提交的函数
// 与默认忽略模式合并(合并提交、撤销、语义版本标签)
ignores: [(commit) => commit.includes('WIP')],
// 是否使用默认忽略模式
// 默认模式:'Merge pull request'、'Revert X'、'v1.2.3' 等
defaultIgnores: true,
// 失败时显示的自定义帮助 URL
helpUrl: 'https://example.com/commit-guidelines',
// 提示配置(用于 @commitlint/cz-commitlint)
prompt: {
messages: {},
questions: {
type: {
description: '选择更改类型:',
},
},
},
};
CLI 使用
安装
# npm
npm install -D @commitlint/cli @commitlint/config-conventional
# yarn
yarn add -D @commitlint/cli @commitlint/config-conventional
# pnpm
pnpm add -D @commitlint/cli @commitlint/config-conventional
常用命令
# 检查上次提交
npx commitlint --last
# 检查一系列提交
npx commitlint --from HEAD~5
# 从特定提交开始检查
npx commitlint --from abc1234
# 从标准输入检查信息
echo "feat: add feature" | npx commitlint
# 从文件检查信息
npx commitlint < .git/COMMIT_EDITMSG
# 使用编辑标志检查(读取 .git/COMMIT_EDITMSG)
npx commitlint --edit
# 使用自定义配置路径检查
npx commitlint --config ./custom-commitlint.config.js
# 打印解析后的配置
npx commitlint --print-config
# 严格模式(警告变为退出码 2)
npx commitlint --last --strict
退出码
| 代码 | 含义 |
|---|---|
| 0 | 成功(无错误) |
| 1 | 发现 lint 错误 |
| 2 | 发现警告(仅限严格模式) |
| 3 | 发现错误(严格模式) |
| 9 | 配置文件缺失(使用 -g 标志时) |
规则参考
Type 规则
| 规则 | 条件 | 默认适用性 |
|---|---|---|
type-enum | type 存在于值中 | always |
type-case | type 的格式为 值 | always, 'lower-case' |
type-empty | type 为空 | never |
type-max-length | type 的字符数不超过 值 | always, Infinity |
type-min-length | type 的字符数不少于 值 | always, 0 |
Subject 规则
| 规则 | 条件 | 默认适用性 |
|---|---|---|
subject-case | subject 的格式为 值 | always |
subject-empty | subject 为空 | never |
subject-full-stop | subject 以 值 结尾 | never, '.' |
subject-max-length | subject 的字符数不超过 值 | always, Infinity |
subject-min-length | subject 的字符数不少于 值 | always, 0 |
subject-exclamation-mark | subject 在 : 前有感叹号 | never |
Scope 规则
| 规则 | 条件 | 默认适用性 |
|---|---|---|
scope-enum | scope 存在于值中 | always, [] |
scope-case | scope 的格式为 值 | always, 'lower-case' |
scope-empty | scope 为空 | never |
scope-max-length | scope 的字符数不超过 值 | always, Infinity |
scope-min-length | scope 的字符数不少于 值 | always, 0 |
Header 规则
| 规则 | 条件 | 默认适用性 |
|---|---|---|
header-case | header 的格式为 值 | always, 'lower-case' |
header-full-stop | header 以 值 结尾 | never, '.' |
header-max-length | header 的字符数不超过 值 | always, 72 |
header-min-length | header 的字符数不少于 值 | always, 0 |
header-trim | header 没有前导或尾随空格 | always |
Body 规则
| 规则 | 条件 | 默认适用性 |
|---|---|---|
body-leading-blank | body 以空行开头 | always |
body-empty | body 为空 | never |
body-max-length | body 的字符数不超过 值 | always, Infinity |
body-max-line-length | body 行的字符数不超过 值(URL 除外) | always, Infinity |
body-min-length | body 的字符数不少于 值 | always, 0 |
body-case | body 的格式为 值 | always, 'lower-case' |
body-full-stop | body 以 值 结尾 | never, '.' |
Footer 规则
| 规则 | 条件 | 默认适用性 |
|---|---|---|
footer-leading-blank | footer 以空行开头 | always |
footer-empty | footer 为空 | never |
footer-max-length | footer 的字符数不超过 值 | always, Infinity |
footer-max-line-length | footer 行的字符数不超过 值 | always, Infinity |
footer-min-length | footer 的字符数不少于 值 | always, 0 |
格式值
对于检查格式的规则(*-case):
[
'lower-case', // 小写
'upper-case', // 大写
'camel-case', // 驼峰式
'kebab-case', // 短横线式
'pascal-case', // 帕斯卡式
'sentence-case', // 句子式
'snake-case', // 下划线式
'start-case', // 起始大写式
]
编程式使用
加载配置
import load from '@commitlint/load';
async function getCommitlintConfig() {
const config = await load();
console.log(config.rules);
return config;
}
验证信息
import load from '@commitlint/load';
import lint from '@commitlint/lint';
async function validateMessage(message) {
const config = await load();
const result = await lint(message, config.rules);
return {
valid: result.valid,
errors: result.errors,
warnings: result.warnings,
};
}
LLM 集成模式
提取规则用于提示生成
从 commitlint 配置生成 LLM 友好的约束:
def extract_rules_for_prompt(config: dict) -> str:
"""从 commitlint 配置中提取规则,转换为 LLM 友好的格式。"""
rules = config.get("rules", {})
prompt_parts = []
# 如果存在 type-enum,则提取
if "type-enum" in rules:
level, applicability, types = rules["type-enum"]
if level > 0 and applicability == "always":
prompt_parts.append(f"允许的提交类型:{', '.join(types)}")
# 如果存在 scope-enum,则提取
if "scope-enum" in rules:
level, applicability, scopes = rules["scope-enum"]
if level > 0 and applicability == "always":
prompt_parts.append(f"允许的 scope:{', '.join(scopes)}")
# 提取 header 长度限制
if "header-max-length" in rules:
level, applicability, max_length = rules["header-max-length"]
if level > 0:
prompt_parts.append(f"header 最多 {max_length} 个字符")
return "\n".join(prompt_parts)
# 用法示例
config = load()
prompt_rules = extract_rules_for_prompt(config)
print(prompt_rules)