husky + lint-staged でコミット前に自動整形・Lintする

目次
フォーマットの揺れや Lint 漏れは、レビューで指摘する前にコミット時に自動で直すのが一番です。husky(git フック管理)と lint-staged(ステージ済みファイルだけ処理)を組み合わせれば、数分で実現できます。
なぜ pre-commit で整形・Lintするのか
- フォーマット差分でレビューが埋もれるのを防ぐ
- 「Lint 通し忘れコミット」をなくす
- ステージしたファイルだけを対象にするので速い(全体を毎回走らせない)
CI でも Lint は回しますが、CI が落ちてから直すより、コミット前に手元で直る方が速いです。
セットアップ
pnpm add -D husky lint-staged
pnpm exec husky inithusky init で .husky/ が作られ、package.json に "prepare": "husky" が追加されます。
この prepare により、pnpm install のたびにフックが自動でセットアップされます(クローン直後も有効)。
pre-commit フックの設定
husky init が作る .husky/pre-commit は初期状態だとテスト実行になっているので、
lint-staged を呼ぶように書き換えます。
# .husky/pre-commit
pnpm lint-stagedlint-staged の設定
.lintstagedrc.json に「どのファイルに何をするか」を書きます。
{
"*.{ts,tsx}": ["eslint --fix", "prettier --write"],
"*.{css,json,md,mjs}": ["prettier --write"]
}- キー: ステージ済みファイルにマッチさせる glob
- 値: マッチしたファイルに実行するコマンド(配列は左から順に実行)
- マッチしたファイル名が引数として渡され、整形結果は自動で再ステージされる
動作の様子
git commit すると、pre-commit が lint-staged を呼び、ログが出ます。
[STARTED] *.{css,json,md,mjs} — 2 files
[STARTED] prettier --write
[COMPLETED] prettier --write
[SKIPPED] *.{ts,tsx} — no files
[STARTED] Staging changes from tasks....ts がステージされていなければスキップ、整形した分は再ステージ、と設定どおりに動きます。
ハマりどころ
- どうしてもフックを飛ばしたい時は
git commit --no-verify tscのようなファイル単位で動かないツールは lint-staged と相性が悪い。型チェックは CI 側に置くのが無難- フックは「ステージ済みファイルだけ」が対象。意図せず対象外になっていないか、初回はログで確認する
CI との役割分担
- husky / lint-staged(手元): コミット前に差分だけを素早く整形・Lint
- CI(GitHub Actions など): プロジェクト全体に Lint・型チェック・ビルドをかける最終防衛ライン
二重に見えますが、役割が違います。手元で軽く弾き、CI で漏れを止める、の二段構えが効きます。
まとめ
husky + lint-staged は、コミット前の自動整形・Lint を数分で導入できます。設定は
.husky/pre-commit と .lintstagedrc.json の2ファイルだけ。フォーマット論争から解放されて、
レビューを本質的な議論に集中させましょう。
関連記事

デプロイ先の環境をブランチで出し分けるとき、secret を FOO_STG / FOO_PROD のように別名で用意して if 分岐する必要はありません。job の environment をブランチから動的に決めれば、Environment secret として「同じ名前」の secret を各環境に置くだけで自動的に出し分けられます。三項演算子っぽい書き方の仕組みと注意点、承認レビューの掛け方まで解説します。

GitHub の Repository ruleset を使って develop / main への直接 push を止め、Pull Request 経由を強制する設定を、個人〜少人数開発の視点でまとめます。Require a pull request before merging が本命であること、Required approvals 0 でも直接 push は禁止できること、Restrict updates を選んではいけない落とし穴、Bypass list の扱い、CI 必須化まで解説します。

Terraform の S3 backend が要求する state バケットを、GitHub Actions の OIDC + IAM ロールで手動ワークフローから作成する手順。backend の鶏卵問題、最小権限ロール、冪等な bootstrap、そして role-to-assume が空になるハマりどころまで解説します。