pre-pushを活用してdevelop, masterへのpushを禁止する方法

2 min read読了の目安(約2300字

gitでチーム開発を行っていて、謝ってmaster, developへ直接pushしてしまう事象が発生しました。
revertすれば戻せますが、ヒューマンエラーを仕組みで無くすにはどうしたらよいかと調べました。

Git hooks

Git hooksでpushする直前もしくは直後に特定を処理を実行することができます。
git cloneした時点で.git/hooks配下にsampleが配置されます。
.sampleを削ればスクリプトとして実行されます。

❯❯❯ ls .git/hooks                                                           
applypatch-msg.sample   fsmonitor-watchman.sample
pre-applypatch.sample   pre-merge-commit.sample
pre-rebase.sample   prepare-commit-msg.sample
commit-msg.sample   post-update.sample
pre-commit.sample   pre-push.sample
pre-receive.sample   update.sample

Git hooksの詳細はこちら[1]を参照してください。


pre-push

pre-pushを使用することでpushする直前に特定の処理を挟むことが出来ます。
push先がmaster, developの場合はエラーとするスクリプトを実装します。c
こちら[2]を参考にさせていただきました。

ファイルの作成

# ディレクトリの作成
mkdir infra/.githooks
# ディレクトリ移動
cd infra/.githooks
# pre-pushファイルの作成
code pre-push

実行権限付与

実行権限を付与しないとpre-pushが動作しないので、忘れずに権限を付与します。

chmod a+x pre-push

実装

pre-push
#!/bin/bash

readonly REJECT_PUSH_BRANCHES=('master' 'develop')

while read local_ref local_sha1 remote_ref remote_sha1
do
    for branch in ${REJECT_PUSH_BRANCHES[@]}; do
        if [[ "${remote_ref##refs/heads/}" = "${branch}" ]]; then
            echo -e "\033[0;32mDo not push to\033[m\033[1;34m ${branch}\033[m \033[0;32mbranch\033[m"
            exit 1
        fi
    done
done

infra.githooksを読み込むよう認識させる

デフォルトでは.git/hooks配下を読み込むようになっています。
なので下記コマンドを実行し、読み込み先を変更します。

git config core.hooksPath infra/.githooks

テスト

$ git push origin master
Do not push to master branch

出来ました!
後はclone後の作業として、README.mdまたはwikiに下記を記載します。

git config core.hooksPath infra/.githooks
chmod a+x infra/.githooks/pre-push

私のプロジェクトではmaven, antを利用しているので
上記のコマンドをmavenビルドした際に実行されるようにしています。
こんな感じに。

build-xml
  <target name="init-git-hooks">
    <exec executable="git" failonerror="true">
      <arg line="config core.hooksPath infra/.githooks" />
    </exec>
    <exec executable="chmod" failonerror="true">
      <arg line="a+x infra/.githooks/pre-push" />
    </exec>
  </target>

これでmaster, developへのpushが阻止できるようになりました!
他にもcommit時も処理を挟めるようなので、commitする前に単体テストを行う等の仕組みを入れてみようかなと思います。
最後まで見てくださりありがとうございました!

脚注
  1. https://qiita.com/noraworld/items/c562de68a627ae792c6c ↩︎
  2. https://qiita.com/sensuikan1973/items/e6ab84403338a874b3aa ↩︎