この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは、黒澤です。
開発を行う中で rebsae を用いて develop
に追従させる運用をしていると、feature
に force push する機会が出てくると思います。
あるとき、こんなミスをしてしまいました。
$ git push -d origin feature/hoge
git push -f
とするところを -d
とタイプミスして push してしまいました。f と d が隣にあるのでなくはないミスだと思います。(そうだよね?)
すると、何が起こるかというと リモートのブランチが消し飛びます。
$ git push -d origin feature/hoge
:
- [deleted] feature/hoge
WIP で作っていた PR もクローズします。
PR 自体は Restore branch
のボタンを押して、Reopen and comment
してやれば復活させることが可能です。
でもこれで「じゃあいいや」で終わる問題かと言えばそうではありません。force push は破壊的な push ができてしまうコマンドです。今回起こった問題以外にも何かやらかしてしまう可能性があります。
そこでなんとかしたいというのが今回の本題です。
Git hooks とは
特定のアクションが行われた際に、スクリプトを実行することができます。今回のケースでいうと push が行われたときにスクリプトを実行して確認を出すのを実現するのに使用します。
スクリプトを書く
hook は通常各プロジェクトの .git/hooks
に格納されています。適当なディレクトリで見てみるとこんな感じになっていると思います。
$ cd .git/hooks/
$ tree
.
├── applypatch-msg.sample
├── commit-msg.sample
├── fsmonitor-watchman.sample
├── post-update.sample
├── pre-applypatch.sample
├── pre-commit.sample
├── pre-push.sample
├── pre-rebase.sample
├── pre-receive.sample
├── prepare-commit-msg.sample
└── update.sample
でも今回はプロジェクト単位ではなく全部に適用したいものなので init.templatedir
を使って指定を行います。
# ディレクトリを作る
$ mkdir -p ~/.git_template/hooks
# push したときに実行するスクリプト
$ vi ~/.git_template/hooks/pre-push
# 実行権限をつける
$ chmod a+x ~/.git_template/hooks/pre-push
# テンプレートに指定する
$ git config --global init.templatedir '~/.git_template'
pre-push
の中身
#!/bin/bash
echo '[warn] push to remote, continue? [y/N]'
exec < /dev/tty
read answer
case $answer in
'y' | 'yes') echo '[info] OK. push start.';;
* ) echo '[error] push failed.';exit 1;;
esac
exit 0
これで push を行なった際に、pre-push
に書いたスクリプトが実行されます。
$ git push -f origin feature/hoge
[warn] push to remote, continue? [y/N]
y
[info] OK. push start.
確認というワンクッションを置くことで f を d に間違えて push するというしょうもないミスは減らせた気がします。今回は push しか設定していませんが他にも様々なアクションに対して hook を設定することができるのでサンプルファイルを参考にすると良いと思います。
また、実行できれば Ruby とか Python でも記述することが可能です。
まとめ
- Git hooks を使おう
- めそ子スタンプをよろしくお願いします!