Bash
Git
GitHub

[Git] 特定のブランチに対するpushを禁止し、ミスをシステム的に防ぐ

はじめに

ブランチ名をターミナルに表示させていてもなお、pushミスしたことはあるでしょうか。 (はい..あります...)
sample_image.png
そんな己の不注意さへの対策には、もはやpush不可能にしておくしかありません。
プルリクベースの運用なら禁止にして問題ないはず。

やること

例えばrelease系ブランチにpushしようとしたら、こんな感じに怒られるようにする。
image.png
Git hookを使って実現できる。

個人として

個人のミスを防止する目的だけなら、ローカルで個別に禁止すればいい。

特定のレポジトリに適用する

# 対象のディレクトリに移動する
$ cd ~/tmp_git_practice

# pre-pushファイルを作成する
$ cd ./git/hooks
$ vim pre-push   # ここにスクリプトを書く

# 実行権限「x」をつける
$ chmod +x pre-push

【pre-pushファイル】1

#!/bin/bash

# pushを禁止するブランチ
readonly MASTER='master'
readonly RELEASE='^.*release.*$'  # 「release」文字列を含む全てのブランチ

while read local_ref local_sha1 remote_ref remote_sha1
do
  if [[ "${remote_ref##refs/heads/}" = $MASTER ]]; then
    echo -e "\033[0;32mDo not push to\033[m\033[1;34m master\033[m \033[0;32mbranch\033[m"
    exit 1
  fi
  if [[ "${remote_ref##refs/heads/}" =~ $RELEASE ]]; then
    echo -e "\033[0;32mDo not push to\033[m\033[1;34m release\033[m \033[0;32mbranch\033[m"
    exit 1
  fi
done

全てのレポジトリに適用する

git inittemplate_directory機能を使って、init/clone時に自動で適用させる。

# template用のディレクトリを作る
$ mkdir -p ~/.git_template/hooks

# push直前に実行するスクリプトファイル。ここに先述のコードを置く。
$ vim ~/.git_template/hooks/pre-push

# 実行権限「x」をつける
$ chmod +x ~/.git_template/hooks/pre-push

# テンプレートに指定する
$ git config --global init.templatedir '~/.git_template'

ただし、これは既存のレポジトリには反映されない。
それがしたい場合は、対象のレポジトリの.git/hooks/pre-pushファイルを置き換え/新規作成すれば良い。

チームとして

チーム全体で運用として禁止するなら、GitHubのProtected Branch機能を使うのが良い。
APIも提供されているので柔軟に対応できる。
image.png


  1. bashの装飾については、ANSI Escape sequencesが参考になります。