くらげになりたい。

くらげのようにふわふわ生きたい日曜プログラマなブログ。趣味の備忘録です。

githookで直push/直commitを禁止にするなど

githooksを試してみたときのメモ(*´ω`*)
いつもミスるので教えてくれるのありがたい。。(*´ω`*)

huskyを使っているので.husky/配下にファイルを配置。 - Husky - Git hooks

特定ブランチへのcommitを禁止する

ファイル: .husky/pre-commit

#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

# protect spec branch
. "$(dirname -- "$0")/scripts/pre-commit-protect-branch.sh"

ファイル: .husky/scripts/pre-commit-protect-branch.sh

#!/usr/bin/env sh

###########################################################
# Protect branch
###########################################################
readonly PROTECTED_BRANCHES="(master|main|develop)"
readonly BRANCH_NAME=`git symbolic-ref HEAD | sed -e 's:^refs/heads/::'`
if [[ "${BRANCH_NAME}" =~ $PROTECTED_BRANCHES ]]; then
  echo "\\033[31m!!! NOT ALLOW COMMIT on "${BRANCH_NAME}" branch!!!\\033[m"
  exit 1
fi

特定ブランチへのpushを禁止する

ファイル: .husky/pre-push

#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

# protect branch and tag
. "$(dirname -- "$0")/scripts/pre-push-protect-branch.sh"

ファイル: .husky/scripts/pre-push-protect-branch.sh

#!/usr/bin/env sh

###########################################################
#  Protect branch/tag
###########################################################
readonly PROTECTED_BRANCHES="(master|main|develop)"
while read local_ref local_oid remote_ref remote_oid
do
  echo "local_ref=${local_ref} local_oid=${local_oid} remote_ref=${remote_ref} remote_oid=${remote_oid}"
  
  # protect tag
  TAG_NAME="${remote_ref/refs\/tags\//}"
  echo "TAG_NAME=${TAG_NAME}"
  if [[ "${remote_ref}" =~ ^refs/tags/.*$ ]]; then
    echo "\\033[31m!!! NOT ALLOW PUSH on '$TAG_NAME' tag!!!\\033[m"
    exit 1
  fi

  # protect branch
  BRANCH_NAME="${remote_ref/refs\/heads\//}"
  echo "BRANCH_NAME=${BRANCH_NAME}, remote_ref=${remote_ref}"
  if [[ "$BRANCH_NAME" =~ $PROTECTED_BRANCHES ]]; then
    echo "\\033[31m!!! NOT ALLOW PUSH on '$BRANCH_NAME' branch!!!\\033[m"
    exit 1
  fi
done

pre-pushの場合は、標準入力で以下の内容が渡ってくるので、
while readで読み取ってその内容にあわせ処理をする

SP SP SP LF

pushする内容がない場合、標準入力も空になるので、
whileループを通らないので注意。

コンフリクトが残っていたらcommitを禁止する

ファイル: .husky/pre-commit

#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

# protect spec branch
. "$(dirname -- "$0")/scripts/pre-commit-protect-branch.sh"

# check remain conflict
. "$(dirname -- "$0")/scripts/check-remain-conflict.sh"

ファイル: .husky/scripts/check-remain-conflict

#!/usr/bin/env sh

###########################################################
# check remain conflict
###########################################################
echo "${BASH_SOURCE[0]}"
conflicts=`git diff --cached --name-only -G"<<<<<|=====|>>>>>" | grep -v "${BASH_SOURCE[0]}"`
FLAG=0
if [[ -n "$conflicts" ]]; then
    for FILE in $conflicts; do
        if [ ! -e $FILE ]; then
          echo "skip $FILE"
          continue
        fi
        echo "\\033[31m!!! REMAIN CONFLICT in $FILE!!!\\033[m"
        FLAG=1
    done;
fi

exit ${FLAG}

おまけ

gitのデフォルトのhooksディレクトリは.git/hooks/

hooksディレクトリの場所はgit config core.hooksPathで変更できる

$ git config core.hooksPath .husky

リポジトリ共通の場合は、--globalをつけてやればOK

$ mkdir ~/.githooks
$ git config --global core.hooksPath ~/.githooks

もしくは、git init時のテンプレートを用意して、そこに配置するのでもOK

$ mkdir ~/.git_template
$ mkdir ~/.git_template/hooks
$ git config --global init.templatedir ~/.git_template/

ただ、あくまでテンプレート。自動更新はされないので注意が必要。


以上!! なんか増えたら追記していこう(*´ω`*)

参考にしたサイト様