Vue.jsはOSSで開発されているJavaScriptのフレームワークであり、その人気からか多くの開発者(記事作成時点で285人)が開発に参加しています。これだけの大人数で開発しているとコードやドキュメントやらが無秩序になるので、そうならないための対策が必要になります。この記事で紹介するのはその対策の一つであるコミットメッセージのルールを自動で守らせる仕組みです。

Vue.jsのソースコードには次のようにあります。
vue/package.json at dev · vuejs/vue
"gitHooks": {
"pre-commit": "lint-staged",
"commit-msg": "node scripts/verify-commit-msg.js" // このJavaScriptでコミットメッセージを制御
},
verify-commit-msg.jsは次のようになっています。
const chalk = require('chalk')
// Gitのコミットメッセージを取得
const msgPath = process.env.GIT_PARAMS
const msg = require('fs').readFileSync(msgPath, 'utf-8').trim()
// 正規表現でメッセージをチェック
const commitRE = /^(revert: )?(feat|fix|polish|docs|style|refactor|perf|test|workflow|ci|chore|types|build)(\(.+\))?: .{1,50}/
if (!commitRE.test(msg)) { // msgが正規表現に一致しなければエラー表示、エラー終了
console.log()
console.error(
` ${chalk.bgRed.white(' ERROR ')} ${chalk.red(`invalid commit message format.`)}\n\n` +
chalk.red(` Proper commit message format is required for automated changelog generation. Examples:\n\n`) +
` ${chalk.green(`feat(compiler): add 'comments' option`)}\n` +
` ${chalk.green(`fix(v-model): handle events on blur (close #28)`)}\n\n` +
chalk.red(` See .github/COMMIT_CONVENTION.md for more details.\n`) +
chalk.red(` You can also use ${chalk.cyan(`npm run commit`)} to interactively generate a commit message.\n`)
)
process.exit(1)
}
我々日本人の上、案件によって適したメッセージは違うのでこれをこのまま使うパターンが最適ということはまずありませんが、基本パターンはコメントにある部分をなぞるのがよいでしょう。小規模案件ならばcommitの種類を絞ってメッセージを日本語にするだけでもだいぶ扱いやすくなります。例えば次です。
const chalk = require('chalk')
// Gitのコミットメッセージを取得
const msgPath = process.env.GIT_PARAMS
const msg = require('fs').readFileSync(msgPath, 'utf-8').trim()
// 正規表現でメッセージをチェック
const commitRE = /^(revert: )?(fix|add|docs|refactor|rm|test|tmp)(\((機能A|機能B|機能C)\))?: .*/
if (!commitRE.test(msg)) { // msgが正規表現に一致しなければエラー表示、エラー終了
console.log()
console.error(
` ${chalk.bgRed.white(' ERROR ')} ${chalk.red(`コミットメッセージの形式が不適正です.`)}\n\n` +
chalk.red(` コミットをするには適切なメッセージ形式が必要です. 例:\n\n`) +
` ${chalk.green(`add(機能A): 機能Aのほげほげを追加`)}\n` +
` ${chalk.green(`fix(機能B): ふがしていた問題を修正`)}\n\n` +
chalk.red(` コミットメッセージは次の正規表現に従っている必要があります.\n`) +
chalk.red(` ${commitRE}\n`)
)
process.exit(1)
}

何かしらフォーマットの定まったコミットがされていると後でgrepするのがとても楽になります。フォーマットを統一する際に個々の良心と注意深さに依存するのは難しいので自動化するのは有効な部類と自分は考えています。