husky の使い方 — モダンなGitフックをプロジェクトに簡単導入
一言でいうと
huskyは、Gitフック(pre-commit、commit-msgなど)をプロジェクト内で簡単に管理・共有できるnpmパッケージです。コミット前のlintやテスト実行を自動化し、チーム全体でコード品質を担保する仕組みを数コマンドで構築できます。
どんな時に使う?
- コミット前にlint/フォーマットを自動実行したい —
pre-commitフックでESLintやPrettierを走らせ、品質の低いコードがリポジトリに入るのを防ぐ - コミットメッセージの規約を強制したい —
commit-msgフックでConventional Commitsなどのフォーマットをチェックする(commitlintとの併用) - プッシュ前にテストを実行したい —
pre-pushフックでユニットテストを走らせ、壊れたコードがリモートに上がるのを防ぐ
インストール
# npm
npm install --save-dev husky
# yarn
yarn add --dev husky
# pnpm
pnpm add --save-dev husky
初期セットアップ
v9系ではhusky initコマンドで初期化するのが推奨されています。
npx husky init
このコマンドを実行すると、以下が自動的に行われます:
.husky/ディレクトリが作成される.husky/pre-commitにサンプルのフックスクリプトが生成されるpackage.jsonのscriptsに"prepare": "husky"が追加される
prepareスクリプトにより、npm install実行時にGitフックが自動で有効化されます。チームメンバーがリポジトリをクローンして依存をインストールするだけで、フックが機能する仕組みです。
基本的な使い方
最も一般的なパターンとして、コミット前にlint-stagedを実行する例を紹介します。
# huskyの初期化
npx husky init
# pre-commitフックの内容を書き換え
echo "npx lint-staged" > .husky/pre-commit
.husky/pre-commitファイルの中身:
npx lint-staged
package.json側の設定例:
{
"scripts": {
"prepare": "husky"
},
"devDependencies": {
"husky": "^9.1.7",
"lint-staged": "^15.0.0",
"eslint": "^8.0.0",
"prettier": "^3.0.0"
},
"lint-staged": {
"*.{ts,tsx}": ["eslint --fix", "prettier --write"],
"*.{json,md}": ["prettier --write"]
}
}
これでgit commitを実行するたびに、ステージングされたファイルに対してESLintとPrettierが自動で走ります。
よく使うAPI(フック設定パターン)
huskyはAPIというよりも、.husky/ディレクトリ内のシェルスクリプトでフックを定義します。以下によく使うパターンを示します。
1. pre-commit — コミット前のチェック
# .husky/pre-commit
npx lint-staged
# フックファイルの作成
echo "npx lint-staged" > .husky/pre-commit
2. commit-msg — コミットメッセージの検証
commitlintと組み合わせて、コミットメッセージの規約を強制します。
# .husky/commit-msg
npx --no -- commitlint --edit $1
echo 'npx --no -- commitlint --edit $1' > .husky/commit-msg
commitlintの設定例(commitlint.config.ts):
import type { UserConfig } from "@commitlint/types";
const config: UserConfig = {
extends: ["@commitlint/config-conventional"],
};
export default config;
3. pre-push — プッシュ前のテスト実行
# .husky/pre-push
npm test
echo "npm test" > .husky/pre-push
4. 複数コマンドの実行
1つのフックで複数の処理を順番に実行できます。
# .husky/pre-commit
npm run typecheck
npx lint-staged
いずれかのコマンドが非ゼロの終了コードを返すと、コミットは中断されます。
5. フックの一時的なスキップ
特定のコミットでフックをスキップしたい場合は、Git標準の--no-verifyフラグを使います。
# pre-commitとcommit-msgフックをスキップ
git commit -m "wip: 作業中" --no-verify
# pre-pushフックをスキップ
git push --no-verify
環境変数でも制御可能です:
HUSKY=0 git commit -m "huskyをスキップ"
類似パッケージとの比較
| 特徴 | husky (v9) | simple-git-hooks | lefthook |
|---|---|---|---|
| 設定方法 | .husky/ディレクトリ内のシェルスクリプト | package.jsonまたは設定ファイル | YAML設定ファイル |
| 依存サイズ | 非常に軽量 | 非常に軽量 | Go製バイナリ(やや大きい) |
| 並列実行 | 非対応(シェルスクリプト次第) | 非対応 | 対応 |
| Node.js依存 | あり | あり | なし(Go製) |
| エコシステム | 最大(lint-staged, commitlint等との連携実績豊富) | 小規模 | 中規模 |
| 学習コスト | 低い | 非常に低い | やや高い |
| モノレポ対応 | 可能(設定が必要) | 限定的 | 充実 |
選定の目安:
- husky — 最も広く使われており、情報量が豊富。一般的なプロジェクトにはこれで十分
- simple-git-hooks — 設定ファイルが1つで済むシンプルさを重視する場合
- lefthook — モノレポや並列実行など高度な要件がある場合
注意点・Tips
v8以前からの移行に注意
v9ではセットアップ方法が大きく変わりました。v8以前のhusky installや.husky/_/husky.shを使ったパターンは不要になっています。既存プロジェクトを移行する場合は、古い.husky/ディレクトリを削除してからnpx husky initをやり直すのが確実です。
CI環境でのフック無効化
CI/CD環境ではGitフックを実行する必要がありません。huskyはnpm ci実行時(prepareスクリプト経由)にフックをセットアップしようとしますが、CI環境では以下のいずれかで対処します。
# 方法1: 環境変数で無効化
HUSKY=0 npm ci
# 方法2: npm ciの--ignore-scriptsフラグ(他のスクリプトも無効になる点に注意)
npm ci --ignore-scripts
GUI Gitクライアントでの動作
SourceTreeやVS CodeのGit機能など、GUIクライアントからコミットした場合もフックは実行されます。ただし、GUIクライアントがNode.jsのPATHを正しく認識できない場合があります。その場合は~/.huskyrc(非推奨)ではなく、フックスクリプト内でPATHを明示的に設定してください。
# .husky/pre-commit
export PATH="/usr/local/bin:$PATH"
npx lint-staged
lint-stagedとの併用がベストプラクティス
pre-commitでプロジェクト全体にlintを走らせると、大規模プロジェクトでは時間がかかりすぎます。lint-stagedを使えば、ステージングされたファイルだけを対象にできるため、コミット体験を損ないません。
モノレポでの使い方
モノレポでは、Gitフックはリポジトリルートの.husky/に配置する必要があります。package.jsonがサブディレクトリにある場合は、prepareスクリプトを調整します。
{
"scripts": {
"prepare": "cd .. && husky ./frontend/.husky"
}
}
まとめ
huskyは、Gitフックをチーム全体で共有・強制するためのデファクトスタンダードなツールです。v9ではnpx husky init一発で初期化でき、.husky/ディレクトリにシェルスクリプトを置くだけというシンプルな設計になりました。lint-stagedやcommitlintと組み合わせることで、コード品質とコミット規約を自動的に担保する開発フローを簡単に構築できます。