Commitlint 是做什麼的?
使用 commitlint 設定與規則驗證提交訊息是否符合 Conventional Commits 格式。
使用時機
請在以下情況下使用此技能:
- 為儲存庫設定 commitlint
- 配置 commitlint 規則與可共用的設定檔
- 將 commitlint 整合到 pre-commit 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"
規則設定
規則以陣列形式配置:[level, applicability, value]
嚴重性層級:
| 層級 | 意義 | 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 | 短標題 | 標題 > 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 以忽略特定提交的函式
// 與預設忽略模式合併(合併提交、還原提交、semver 標籤)
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 存在於 value 中 | always |
type-case | type 符合 case value 格式 | always, 'lower-case' |
type-empty | type 為空 | never |
type-max-length | type 長度小於等於 value | always, Infinity |
type-min-length | type 長度大於等於 value | always, 0 |
主旨(Subject)規則
| 規則 | 條件 | 預設適用性 |
|---|---|---|
subject-case | subject 符合 case value 格式 | always |
subject-empty | subject 為空 | never |
subject-full-stop | subject 以 value 結尾 | never, '.' |
subject-max-length | subject 長度小於等於 value | always, Infinity |
subject-min-length | subject 長度大於等於 value | always, 0 |
subject-exclamation-mark | subject 在 : 之前有驚嘆號 | never |
範圍(Scope)規則
| 規則 | 條件 | 預設適用性 |
|---|---|---|
scope-enum | scope 存在於 value 中 | always, [] |
scope-case | scope 符合 case value 格式 | always, 'lower-case' |
scope-empty | scope 為空 | never |
scope-max-length | scope 長度小於等於 value | always, Infinity |
scope-min-length | scope 長度大於等於 value | always, 0 |
標題(Header)規則
| 規則 | 條件 | 預設適用性 |
|---|---|---|
header-case | header 符合 case value 格式 | always, 'lower-case' |
header-full-stop | header 以 value 結尾 | never, '.' |
header-max-length | header 長度小於等於 value | always, 72 |
header-min-length | header 長度大於等於 value | always, 0 |
header-trim | header 前後無空白字元 | always |
內文(Body)規則
| 規則 | 條件 | 預設適用性 |
|---|---|---|
body-leading-blank | body 以空白行開頭 | always |
body-empty | body 為空 | never |
body-max-length | body 長度小於等於 value | always, Infinity |
body-max-line-length | body 的行長度小於等於 value(URL 除外) | always, Infinity |
body-min-length | body 長度大於等於 value | always, 0 |
body-case | body 符合 case value 格式 | always, 'lower-case' |
body-full-stop | body 以 value 結尾 | never, '.' |
結尾(Footer)規則
| 規則 | 條件 | 預設適用性 |
|---|---|---|
footer-leading-blank | footer 以空白行開頭 | always |
footer-empty | footer 為空 | never |
footer-max-length | footer 長度小於等於 value | always, Infinity |
footer-max-line-length | footer 的行長度小於等於 value | always, Infinity |
footer-min-length | footer 長度大於等於 value | 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"允許的範圍:{', '.join(scopes)}")
# 提取 subject-case(若存在)
if "subject-case" in rules:
level, _, case = rules["subject-case"]
if level > 0:
prompt_parts.append(f"主旨格式:{case}")
# 提取 header-max-length(若存在)
if "header-max-length" in rules:
level, _, max_len = rules["header-max-length"]
if level > 0:
prompt_parts.append(f"標題最大長度:{max_len} 個字元")
return "\n".join(prompt_parts)
與 @commitlint/prompt-cli 整合
# 互動式提交訊息建立
npx commit
# 使用自訂設定
npx commit --config ./commitlint.config.js
# 使用指定鉤子
npx commit --hook .husky/commit-msg