2019/03/04 追記
古い記事のため参照している人も少ないと思いますが、もしこの記事を参考に導入を考えているかたは、よりモダンかつ高機能な husky を利用することをおすすめします。
このエントリで解決できること
- テストやLintなどを通らない問題のあるコードがGit上でコミットされ、プッシュされることを防げるようになる
- 上記をチームメンバー全員にむけて共有する方法がわかる
- 実際にそのサンプルプロジェクトに触れて、一連のフローを理解できる
はじめに
GitにはHookという機能があり、コミットやプッシュなどに合わせて、特定のシェルスクリプトを走らせることが可能となっています。
この機能を利用すると、作業の自動化などが出来るほか、最も効果的な用法として、「コミット前の機械的なコードチェック」が可能という点があります。
これは、Git Hookがもつ、「終了コードが1の場合は該当処理を取り消す」という機能を用いることによって、例えばテストが通らないコードや、そもそもテストコードを書いていないコードや、コーディング規約を守っておらず、Lintが通らないコードのコミットをさせないということができるということです。
チームで作業している時には、コードの品質やできるだけ一定以上で固定したいもの。
それらを解決できるのがGit Hookとなります。
しかしながらこのGit Hook、.git
の管理下となるため、Git上にコミットできないため、他のチームメンバーと共有しづらいという問題を抱えています。
その問題を解決方法の一つとして、npmモジュールpre-commit
が有効であったため、ご紹介します。
導入
はじめに
まずはpre-commitの導入が必要です。
また、pre-commit時に走らせる何らかのテストも必要なので、今回は一番簡単に検証できるESLintを使ってみることにしました。
また、今回はpre-commit部以外はそこまで重要でないため、面倒な手順をスキップするためGitHubにてサンプルプロジェクトを用意しましたので、こちらをCloneして確認していくこととします。
環境
既にNode.js及びnpmが導入されている環境を対象としております。
また、今回こちらで実行している環境は以下となります。
- Node.js 6.5.0
- npm 3.10.3
サンプルプロジェクトでの実行準備
まずはサンプルのプロジェクトを用意します。
git clone
した後に、既に設定してあるnpmモジュールを一通り読み込んで、準備完了です。
$ git clone https://github.com/potato4d/pre-commit-sample
$ cd pre-commit-sample
$ npm install
実際に問題のあるコードをコミットしてみる
準備ができたので、さっそく問題のあるコードをコミットしてみましょう。
今回のサンプルプロジェクトでは、ES2015以降を前提として、var
の利用を禁止しています。
そのため、var
を利用するとエラーが出るような仕組みになっているので、まずは既存のconst
をvar
に書き換えてみます。
var Name = "Tom";
console.log(Name);
以上の状態でファイルを保存し、Gitにコミットしてみます。
$ git add -A
$ git commit -m "エラーが出るかテスト"
結果は以下のようになり、コミットが行われていない場合は成功です。
/path/to/pre-commit-sample/index.js
1:1 error Unexpected var, use let or const instead no-var
✖ 1 problem (1 error, 0 warnings)
pre-commit:
pre-commit: We've failed to pass the specified git pre-commit hooks as the `test`
pre-commit: hook returned an exit code (1). If you're feeling adventurous you can
pre-commit: skip the git pre-commit hooks by adding the following flags to your commit:
pre-commit:
pre-commit: git commit -n (or --no-verify)
pre-commit:
pre-commit: This is ill-advised since the commit is broken.
pre-commit:
Potato4ds-Macbook:pre-commit-sample potato4d$
ちなみに実際の画面では色がついて表示されるはずです。
このように、設定さえ完了してしまえば、それだけでプロジェクトにとって望ましくないコードのコミットを制限することが出来ます。
pre-commitの条件の設定方法
ここまでサンプルプロジェクトを利用してまずは実際の挙動を確認してもらいましたが、続いて設定の方法をご紹介します。
といっても設定方法は簡単で、package.json
に追記するだけとなります。
package.json
を開いた上で、末尾の以下の項目を確認してください。
"pre-commit": [
"test"
]
}
このpre-commit
上に定義されているスクリプト名が全て自動で実行される仕組みとなっているため、動かしたいスクリプト名を指定するだけの仕組みとなっています。
この時のスクリプト名はnpm scriptの名前となっており、実際に実行されるコマンドはnpm run $precommit-name
の形式となります。
サンプルでは、eslint .
が動くようにscripts
側で定義していたため、そのとおりに動くこととなりました。
まとめ
- pre-commitはGitがもつHookの仕組みであり、問題がある場合はコミットを中断することが出来る機能となる
- pre-commitモジュールを利用すると、チーム全体でコミット時の低品質コードの混入を防ぐ仕組みを共有できる
- pre-commitの定義に関しては、package.jsonで行い、任意のnpm scriptを実行できるようになる
おわりに
pre-commitを行うモジュールやプラグインに関しては、みたところNodeに限らず、PHPやRubyでも提供されています。
個人的にはNode製のものが使い勝手がよく、利用していますが、言語を選ばない機能であるため、プロジェクトへの導入は難しくなさそうです。
pre-commitは最近、実際の現場でも導入し始めましたが、CI任せであった部分で、WIPのコードはたびたびコケていたのが解消されて、恩恵は十分にあるように感じました。
個人開発なら好き放題書いてしまってもなんとかなることも多いですが、チーム開発時には存分に効力を発揮してくれる存在となりそうです。