Quantumleap
1435 words
7 minutes
commitlint+huskyでgitのコミットメッセージ問題から解消されよう
2024-02-13

背景#

ESLintやPrettierでファイルはちゃんとフォーマットしているのにコミットメッセージは人によってめちゃくちゃだったりします。

ルールも決まっていないと後から読み返したときに何をしたんだこれとなるのですが、とはいえ毎回「どんなルールだったっけ」とプロジェクトごとに見返すのもめんどくさいです。

あと、コミットしてから「あ、フォーマットするの忘れてた」となって再コミットするのもダサいです。

これらを全て解決する方法が求められていました。

Husky#

huskyはgitで何らかの操作を行った際に割り込んで処理が行える仕組みを提供します。

例えば、コミットする際にはgit commitが実行される前にyarn lintyarn testを実行するなどといった操作ができるようになります。

こうすればコミットされた内容はCIでのテストをパスすることが保証されるようになります。

この仕組みの便利なところはESLintとPrettierの基準を満たすかどうかをチェックしているのではなく、実際にこの時点で整形してくれることにあります、とても便利。

とはいえテストが通らないコミットができないのは困るので、テスト自体は通らなくても良いですがESLintとPrettierの整形は通って欲しい感じになります。

Huskyはつい最近アップデートがあったようで、使い方が大きく変更されています。ネットで検索しても違うコマンドが載っていたりして困ります。

導入#

プライベートレポジトリでないなら以下の二つをインストールします。

yarn add -D husky pinst
yarn husky init

プライベートの場合はpinstは不要のようです

yarn husky initについては不要かもしれませんが、一応実行しました。

これでpackage.jsonscripts"prepare": "husky"が追加されていればOKです。

.
├── .husky/
   ├── _/
   └── pre-commit
└── package.json

この時点で上のような構成になっていると思います。

lint-staged#

コミット前にESLintを実行させることができます。

yarn add -D lint-staged

としてパッケージを追加し.lintstagedrc.yamlを作成します。

---
'**/*.ts':
  - yarn lint
  - yarn format

こう書くとコミット内容に.tsのファイルがあればyarn lintyarn formatを実行してくれます。

最後にこの処理がgit commitが実行される前に実行されてほしいので.husky/pre-commitを編集します。

yarn test
yarn lint-staged

ここのyarn testは必ずしも必要ではない、大事なのはyarn lint-stagedが実行されること

.
├── .husky/
   ├── _/
   └── pre-commit
├── .lintstagedrc.yaml
└── package.json

するとこんな感じになると思います。

commitlint#

commitlintはコミットメッセージが.commitlintrc.yamlに設定されたルールに則っているかをチェックするパッケージです。

yarn add -D @commitlint/cli @commitlint/config-conventional

インストールができたら.commitlintrc.yamlを作成します。

---
extends:
  - '@commitlint/config-conventional'

今回は特に何も入れていませんが、ここにプロジェクトごとのルールを追記することができます。

最後にコミットメッセージを書き込んだ後にチェックを行うので.husky/commit-msgのファイルを作成します。

yarn commitlint --edit ${1}

こうすれば最後のコミットメッセージを読み込んでcommitlintが実行されます。

.
├── .husky/
   ├── _/
   ├── commit-msg
   └── pre-commit
├── .commitlintrc.yaml
├── .lintstagedrc.yaml
└── package.json

するとここまでのファイル構成はこうなります。

実際にどんな挙動をするか確かめたい場合はcommit-msgの最後にexit 1を入れれば必ず失敗するので実際にコミットログが作成されません。

その状態でgit commit -m "testing pre-commit code"みたいな感じで実行すればどうなるかがわかります。

正常に動作していればcommitlintがエラーを返すはずです。

もしcommitlintがちゃんと動いていないようであればHuskyがhookに失敗しているのでyarn installhuskyをインストールしてください。

cz-commitlint#

cz-commitlintはcommitlintの拡張で、対話式でコミットメッセージが作成できるパッケージです。

commitlintと組み合わせて入力ミスを防ぎつつ、フォーマットに則ったコミットメッセージが書けます。

yarn add -D @commitlint/cz-commitlint commitizen

エラーが発生する場合はinquirer@8もインストールしてください

インストールが完了したらpackage.jsonを編集して、

{
  "scripts": {
    "commit": "git-cz"
  },
  "config": {
    "commitizen": {
      "path": "@commitlint/cz-commitlint"
    }
  }
}

を追記します。こうするとyarn commitで対話式のコミットメッセージが書けます。

git commit#

とはいえgit commitに慣れているので、このコマンドを実行したときにもyarn commitと同様の効果が得られてほしいです。

そこで.husky/prepare-commit-msgを作成して以下の内容を書き込みます。

exec < /dev/tty && yarn cz --hook || true

これはyarn czを実行してその結果がtrueであればexec 0を返すコードです。

Huskyは0以外の値を返すとエラーとしてコミットがなかったことになります。

ttyを入れないと対話式にならない(何も入力できない)

├── .husky/
   ├── _/
   ├── prepare-commit-msg
   ├── commit-msg
   └── pre-commit
├── .commitlintrc.yaml
├── .lintstagedrc.yaml
└── package.json

最終的にファイルの構成は上のようになります。

これでコミットメッセージに悩まされる日々から無事に開放されました、やったね。

でもこのレポジトリにはこの機能を実装していないという矛盾(おい

記事は以上。

commitlint+huskyでgitのコミットメッセージ問題から解消されよう
https://fuwari.vercel.app/posts/2024/02/commitlint_husky/
Author
tkgling
Published at
2024-02-13