リモートのmasterブランチへのpushを禁止する

Git使い始めの「あるある」ですが、リモートのmasterブランチにいきなりpushして怒られたり、されて発狂したりってよくあります。グランフェアズもpull requestベースで運用しているので、ローカルにmasterブランチはいらないし、リモートのmasterには間違っても直接pushして欲しくないのです。

今日も、Git練習中の“うっかりチカちゃん”が作業ブランチをいきなりリモートのmasterにpushしちゃったので…「そうだね、プッシュできちゃうのがダメなんだね、そもそもプッシュできないようになってないとね…」ということで出来なくすることにしました。(環境はWindowsです)

プロジェクト単位で手動設定編

ローカルのプロジェクト作業ディレクトリにGitのhookファイルを作成して制御します。つまりこの方法だと、プロジェクトごとにhookファイルをコピー(作成)しないといけないってことですね。

まずはプロジェクト作業ディレクトリの.githookフォルダ内にpre-pushファイルを作成。Windowsの場合は手動で作れば良い。

hookファイルの設置場所

{project-dir}.githookspre-push

作成したpre-pushファイルに次を記述

#!/bin/bash
while read local_ref local_sha1 remote_ref remote_sha1
do
  if [[ "${remote_ref##refs/heads/}" = "master" ]]; then
    echo "Do not push to master branch!!!"
    exit 1
  fi
done

Windows以外の場合は、作ったhookファイルに実行権限を付与する必要があります。(Windowsでは不要)

chmod 775 pre-push

これでローカルの制御は完了。リモートのmasterにpushしようとすると、「Do not push to master branch!!!」というエラーが出てプッシュ完了できなくなります。

別のプロジェクトで同じ設定にしたい場合は、pre-pushファイルをコピーして{project-dir}.githooksに設置します。

自動でファイルが設置されるようにする編

上記の設定だと、プロジェクトを追加するたびに手動でhookファイルをコピーしてこないといけないので忘れがち。ということで、リモートからプロジェクトファイルをcloneしたタイミングで、hookファイルが自動でコピー・設置されるようにする場合はこちら。

pre-pushファイルをテンプレートディレクトリに設置

まずは「プロジェクト単位で手動設定編」で作成したpre-pushファイルをWindowsのユーザーホームC:Users{yourName}もしくは、どこか設定ファイルをまとめて管理しているディレクトリに設置します。私の場合、C:varsettingに設定ファイルをまとめているのでここに置く事にしました。

C:varsetting.git_templatehookspre-push

※この場合、ディレクトリ名の「.」はほとんど意味なしです。(設定ファイルぽくしてるだけで) ※Windows以外の場合、設置したファイルに実行権限の付与が必要。

.gitconfigファイルに設定を追加

次に.gitconfigファイルを開いて次の記述を追加します。

[init]
  templatedir = C:varsetting.git_template

※上記のはエディターによってはバックスラッシュ「」に読み替えてください。「」1つだとエラーになって.gitconfigが動かないので2つで。

これで、clone時に自動で.git/hook/pre-pushが設置されるようになりました。
めでたし!(・∀・)v

さいごに

いずれにせよこの方法は、ローカルに設定するかしないか担当者次第になってしまうのが難点。みなさんも書いてるように、GitHubとかBitBucketがサーバ側でmasterへのpushを禁止できるような機能を追加してくれれば一番いいのになぁと思いますね。ちょっと待ってれば実装されるかなー?期待して待つことにしましょう。

以下のサイトを参考にさせていただきました。多謝!

masterへのpushを禁止するローカルgit hookの正しい書き方
masterブランチにpushさせないようにするフック
masterのpushを常に禁止する