git config や gitignore にもカレントとグローバルの設定があるように、
git hooks などにも global な設定があるのかとぼんやり思っていたけれど、違う様子。
「テンプレートファイルがカレントレポジトリにコピーされる」という仕組みみたいだ。
落とし穴
- ファイルコピーは
git clone
とgit init
時におこなわれる- 最初に git 管理を始める時以外に
git init
を使うという発想がなかった
- 最初に git 管理を始める時以外に
- なおかつ
git init
では既に存在するファイルの上書きはおこなわれない (コピーが必要なものは、いったんファイルを削除する必要がある)- 例:
rm .git/hooks/pre-push
git init
- 例:
- git hooks はカレントレポジトリのものが使われる。(テンプレートファイルは直接使われない)
- 今思えば gitconfig に
template
とかinit
とかいう名前が付いている時点で気付いても良かった気もする
gitconfig の例
~/.gitconfig
には「テンプレートのディレクトリ」を指定する。
[init]
templatedir = ~/.git_templates
git hooks のテンプレート例
~/.gitconfig
で指定したディレクトリに、テンプレートとしてコピーしたいファイルを作る。
ここでは試しに「どうやっても push 出来ない git hooks 」を作ってみる。
mkdir -p ~/.git_templates/hooks/
echo "echo Nobody can git push! && exit 1" > ~/.git_templates/hooks/pre-push
chmod +x ~/.git_templates/hooks/pre-push
ちなみに hooks/pre-push で push を止めるには exit を 0 以外で終わらせる必要があるっぽい。
git clone の例
git clone すると、テンプレートファイルから .git/hooks/pre-push
がレポジトリにコピーされるのが分かる。
git clone https://github.com/your/some_repository
cd some_repository
カレントの .git
ディレクトリの中身を確認してみよう。
cat .git/hooks/pre-push
echo Nobody can git push! && exit 1
テンプレートファイルからコピーされているのが分かる。
既存レポジトリの git hooks 更新する場合
ローカルレポジトリに既に .git/hooks/pre-push
が存在する場合は、いったん削除してから init し直せば良い。
rm .git/hooks/pre-push
git init
Reinitialized existing Git repository in /path/to/local/repository/.git/
自動での上書きはおこなわれない様子。
参考
Document
git-init - Create an empty Git repository or reinitialize an existing one
...
TEMPLATE DIRECTORY
Files and directories in the template directory whose name do not start with a dot will be copied to the $GIT_DIR after it is created.
Qiita
- gitでmasterへのpushを防ぐhook - Qiita
- gitでmasterへのpushを禁止する - Qiita
- git で remote master ブランチへのプッシュを禁止する - Qiita
Versions
- git version 2.17.1
Links
チャットメンバー募集
何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。