overcommitとは?
git hooksの管理と、その拡張を簡単にできるRuby製ツールです。同様のツールにpre-commit by YelpやRailsに特化したpre-commitがあります。overcommitはこれらのツールと違い、pre-commit以外のフックにも対応しています。
リポジトリはこちら
overcommitの導入でできること
- コミットのタイミングでrubocopやeslintなどlintツールをかけられる
- コードの読みやすさが向上することを期待できます
- checkoutやpullのタイミングで
bundle install
やnpm install
を実行できる- 他の開発者が
Gemfile
やpackage.json
に追加したらしくなんか動かない問題を回避できる
- 他の開発者が
- pushする前に変更したファイルのみ対象に
rspec
を実行できる- CIする前に自分が行った変更の結果を再確認できるので、少なくとも自分が書いたコードに問題がないか確認できる
- コミットコメントのフォーマットをチェックできる
- 1行80文字以下に収めることで
git log
実行時の一覧性をあげたり、不当に大きなコミットにならないように示せる
- 1行80文字以下に収めることで
- 既存のgit hookを使い回せる
- CustomScriptというHookがあり、これを使うと既存のhookに処理を委譲できます
制限事項
- 残念ながらgit-worktreeには未対応とのこと
インストール
overcommitはRuby製のツールなので、Rubyのインストールを忘れずに。その後、rubygemsで配布されているので下記のコマンドでOKです。rvmやrbenvを使っている方は適宜コマンドを補完してください。
$ gem install overcommit
その後、overcommitを利用したいリポジトリで下記のコマンドを実行します。もし既存のgit hook
を利用している場合は、そのファイルをバックアップしておきましょう。上述した通り、CustomScript
として再利用できます。バックアップをお忘れなく
$ cd git-repo
$ overcommit --install
これでovercommitのベースとなるhookが対象のgitリポジトリにインストールされました。試しに適当なファイルをコミットしてみましょう。
こんな感じで最初はRun
overcommit --sign if you trust the hooks in this repository.
と出ます。overcommit --sign
はovercommit経由で実行するスクリプトのハッシュを記録しておき、fetchした時に不正にスクリプトが書き換わって意図しない動作を防ぐための機構です。overcommitに何も登録していない状態ではコミットメッセージのチェックだけなので、signしてしまいましょう。
$ overcommit --sign
を実行後、再度git commit
をすると下記のようにコミットメッセージがチェックされるはずです。
リポジトリからのアンインストールも下記のコマンドでおkっす
$ overcommit --uninstall
設定方法
設定ファイルたる.overcommit.yml
を書き換えたらovercommit --sign
を実行するのを忘れずに
pre-commit
Rubocopの設定
overcommitの設定は、.overcommit.yml
ファイルに記述します。例えばコミット前のタイミング(言い換えればpre-commit)でrubocop
を実行したいのであれば、下記のように.overcommit.yml
を設定します。
PreCommit:
RuboCop:
enabled: true
command: ['bundle', 'exec', 'rubocop'] # bundlerの中でrubocopを実行する場合
これで、.rb
やGemfile
の変更がcommit
される前にrubocop
のチェックが走ります。1行目のPreCommit
はpre-commit
グループにフックを追加する、という意味で、フックポイントごとにグループを宣言します。
commandは実際に実行するコマンドを記述します。実行ファイルが渡される前に部分と考えていいでしょう。
ESLintの設定
同様にESLintのチェックを行いたい場合は下記のように.overcommit.yml
を記述します。(overcommit側のメッセージ解析の都合上、package.json
も調整が必要です)
ESLint:
enabled: true
required_executable: 'npm'
command: ['npm', 'run', 'lint']
{
"scripts": {
"lint": "eslint -f compact"
},
"devDependencies": {
"eslint": "^2.0.0"
}
{
ESLintの場合、jsファイル等がステージングにある時に実行されます。詳しくはhookのソースをみるとよいです。
required_executable
は必要な実行ファイルを指定する設定です。相対パスの場合はリポジトリ内のパス、そうでない場合はPATH上に存在するかどうかをチェックします。npmはPATHに存在しなければ実行できないので、指定する必要があります。これがないと、npm run lint
が動作しません。
カスタムスクリプト
すでにスクリプトを利用している場合は下記の設定
CustomScript:
enabled: true
required_executable: '.pre-commit.sh' # スクリプトのパスを指定する
post-checkout
bundle install
他のブランチをcheckoutしたタイミングでgem fileの更新をしたい場合は下記のように.overcommit.yml
を設定しましょう
PostCheckout:
BundleInstall:
enabled: true
npm install
npm installの場合もこんな感じです。
NpmInstall:
enabled: true
ここまでの設定を全て有効にする場合、.overcommit.yml
はこんな感じになっているでしょう。
PreCommit:
RuboCop:
enabled: true
command: ['bundle', 'exec', 'rubocop'] # bundlerの中でrubocopを実行する場合
ESLint:
enabled: true
required_executable: 'npm'
command: ['npm', 'run', 'lint']
CustomScript:
enabled: true
required_executable: '.pre-commit.sh' # スクリプトのパスを指定する
PostCheckout:
BundleInstall:
enabled: true
NpmInstall:
enabled: true
これらのHookの詳細はリポジトリの説明からたどることができます。
こんな感じでプロジェクトに必要なhookを組み合わせて設定できます。
FAQ
コミット時に特定のHookをスキップしたい
$ SKIP=RuboCop git commit
コミット時に全てのHookをスキップしたい
OVERCOMMIT_DISABLE=1 git commit