Lefthook の導入事例
開発プロセスを効率化するために導入した Git フックマネージャー の Lefthook を紹介します。
Lefthook 導入の背景
モチベーション1: 手動確認の限界
acomo ではレビュー前にビルド成功や型チェックを手動確認していましたが、以下の課題がありました:
- レビュー後のエラー発覚: 修正作業後にリントや型エラーが見つかる
- 影響の広がり: エラーのあるブランチがマージされ環境に悪影響が出る
これを未然に防ぐため、自動的にチェックを行い早期発見する仕組みが必要でした。
モチベーション2: 他アプローチでの課題
初めに CI/CD パイプライン(例: GitHub Actions)を試しましたが、以下の課題がありました:
- パイプライン競合: 他ジョブとの競合頻度が増加
- 生産性: 結果待ち時間の発生
-
通知: 作業者に通知を送る仕組みの手間(
Slackに送りたい場合のユーザ名変換など)
より簡単かつ早い段階で問題を検出するために、Git フック の活用を検討しました。
ただし、従来利用していた husky + lint-staged はモノレポで設定が煩雑なため、代わりにシンプルな Lefthook を導入しました。
次に、Git フック の基本について説明します。
Git フック の基本
Git フック は、特定の Git 操作(例:コミット、プッシュ、マージなど)の前後にスクリプトを自動実行する Git の機能です。
-
フックの配置場所:
.git/hooks/ディレクトリ内- 💡
git init時にサンプルスクリプトが格納されている
- 💡
-
フックの種類:
-
pre-commit: コミット前に実行 -
post-merge: マージ後に実行 -
commit-msg: コミットメッセージの検証
-
Git フックマネージャー の役割
Git フックマネージャー は、Git フック を便利に管理するツールで、以下の役割があります:
-
バージョン管理: フックスクリプトをリポジトリ内で管理し、チーム共有が可能
- 💡
.git/hooks/ディレクトリはリポジトリの管理対象外なため
- 💡
- セットアップの簡略化: 簡単にフックを設定可能
- 結果の要約表示: 実行したスクリプトの要約表示
次に、Lefthook について説明します。
高速で柔軟な Lefthook
Lefthook は、高速で柔軟な Git フックマネージャー です。Go 言語で開発されており、以下の特徴を持ちます:
-
軽量かつ高速:
- 単一バイナリで依存関係が不要
- 並列処理に対応し、スクリプト実行が高速
-
ポリグロット対応:
- フロントエンドとバックエンドの両方をサポート
-
シンプルな設定:
-
.lefthook.ymlファイルで簡単にフックを設定可能
-
次に、Lefthook と husky + lint-staged について比較をしてみます。
Lefthook と husky + lint-staged の比較
| 機能 | Husky + lint-staged | Lefthook |
|---|---|---|
| モノレポ対応 | プロジェクトごとの個別設定 | リポジトリルートに設定 |
| 並列実行 | 非対応 | 対応 |
| バージョン管理 | 対応 | 対応 |
| 個人設定 | 非対応 | 対応 |
| クロスプラットフォーム | Node環境 | 対応 |
| スクリプトの見通し |
.husky/* 各ファイルを確認する |
設定ファイルにまとまっている |
また、Lefthook には、体系的なドキュメントがあります:
さらに、ステージングファイル操作が Lefthook で完結できる点も魅力です。
次に、Lefthook のセットアップ、実行について説明します。
Lefthook セットアップ方法
-
インストール:
# lefthook をインストールする npm i -D lefthook # lefthook.yml 作成 npx lefthook install -
設定:
lefthook.ymlの例pre-push: commands: textlint: glob: "*.md" run: npm run lint:text:fix {push_files} markdownlint: glob: "*.md" run: npm run lint:markdown:fix {push_files}💡設定時のヒント
-
Git フック名
-
Git公式ドキュメントを確認
-
-
lefthook uninstall-
lefthookの影響を受ける Git フックをクリア
-
-
lefthook run {フック名}-
lefthook run pre-pushのように、{フック名}に設定したスクリプトを手動実行できる
-
-
ファイルテンプレート
- 実行時、適切なファイルに置き換えられるテンプレート機能がある(例:
{staged_files})
- 実行時、適切なファイルに置き換えられるテンプレート機能がある(例:
- コマンド
- オプション
- 参考例
-
Git フック名
-
フックを反映する:
# 設定内容を .git/hooks に反映する # 🐱重要🐱: 変更 → 反映を忘れずに行うこと!!! npx lefthook installこれで、
git フック時に対応するスクリプトが実行されるようになりました。実行例
acomo-zenn on feature/lefthook [⇡] is 📦 v1.0.0 via v20.17.0 at 16:47:23 ❯ git push ╭─────────────────────────────────────╮ │ 🥊 lefthook v1.10.9 hook: pre-push │ ╰─────────────────────────────────────╯ ┃ markdownlint ❯ > acomo-zenn@1.0.0 lint:markdown:fix > npm run lint:markdown -- --fix articles/progress-acomo-2025-01-21-09-33-25.md > acomo-zenn@1.0.0 lint:markdown > markdownlint-cli2 articles/**/*.md README.md --fix articles/progress-acomo-2025-01-21-09-33-25.md markdownlint-cli2 v0.17.2 (markdownlint v0.37.4) Finding: articles/**/*.md README.md articles/progress-acomo-2025-01-21-09-33-25.md Linting: 3 file(s) Summary: 0 error(s) ┃ textlint ❯ > acomo-zenn@1.0.0 lint:text:fix > npm run lint:text -- --fix articles/progress-acomo-2025-01-21-09-33-25.md > acomo-zenn@1.0.0 lint:text > textlint articles/**/*.md README.md --fix articles/progress-acomo-2025-01-21-09-33-25.md ──────────────────────────────────── summary: (done in 1.45 seconds) ✔️ markdownlint ✔️ textlint Enumerating objects: 11, done. Counting objects: 100% (11/11), done. Delta compression using up to 12 threads Compressing objects: 100% (6/6), done. Writing objects: 100% (6/6), 2.03 KiB | 2.03 MiB/s, done. Total 6 (delta 4), reused 0 (delta 0), pack-reused 0 remote: Resolving deltas: 100% (4/4), completed with 4 local objects. To github-prg:example.com/acomo-zenn.git 31323da..6b62658 feature/lefthook -> feature/lefthook最後に概要があり、結果がとても分かりやすい。
問題があった場合は、
git操作は中断されるため、クリーンな状態に保つことができる。
まとめ
Lefthook を導入することで、作業の効率化やミスの削減が期待できます。モノレポ対応や並列処理による高速化も魅力的です。
効率的なフック設定とトラブルの早期検出により、コード品質の向上と安心感を持った開発が可能になります。さらに、柔軟な設定や豊富なオプションで、プロジェクトに合わせた最適なカスタマイズが行えます。
「手作業での都度確認で、やり忘れが頻発している」と感じる方々に、本記事がお役に立てれば幸いです。
Discussion