はじめに
検証用ブランチなどに push しようとしたのに、間違えて main などの重要なブランチに push してしまうというのは、できる限り避けたい事象です。
そんなことしないと思っていても、そこそこ事例があるので備えておくに越したことはありません。
この記事では、ローカルでできる対策をいくつか紹介します。
逆に、リモートであったり、GitHub 等のサービス特有の設定などは紹介しません。
git hooks の利用
pre-push フックを利用して、オブジェクトの転送がされる前に検査を行い、特定のリモートブランチが指定されていた場合に止める方法です。
これは最もよく見る対策方法だと思います。
以下は main, master ブランチへの push を止めるスクリプトです。
#!/bin/bash
remote=$1
while read local_ref local_sha remote_ref remote_sha; do
if [ "$remote_ref" = "refs/heads/main" ] || [ "$remote_ref" = "refs/heads/master" ]; then
echo "Cannot push to main/master branch directly"
exit 1
fi
done
exit 0
chmod +x .git/hooks/pre-push などを実行して、実行権限を渡すのを忘れないようにしてください。
--no-verify オプションによって、このフックの動作はスキップすることができます。
$ git push --no-verify origin main
branch.<name>.pushRemote を無効な remote に向ける
面倒くさがりな人だと、push.default=current のような設定をしていることがあると思います。
そのような場合、main ブランチにいる状態で git push だけで実行するとリモートの main ブランチに push されてしまいます。
そういったことを防ぐ方法です。
$ git config branch.main.pushRemote disabled
$ git config branch.master.pushRemote disabled
$ git config remote.disabled.url "Cannot push to main/master branch directly"
1,2 行目の記述のみで良いようにも思えますが、disabled という名前のリモートリポジトリを設定していると動いてしまうので、3 行目で無効な URL を remote に設定して、より安全にしています。
とはいえ、確実に設定しないリモートの名前にしておけば十分です。
実際に push してみようとすると、以下のようになります。
$ git push
fatal: 'Cannot push to main/master branch directly' does not appear to be a git repository
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
そこそこハッキーな感じがしますね。
git push origin main のように省略せずに push する場合、この設定は何の効果もありません。
おわりに
今回はローカルでできる制限方法のみを紹介しました。
リモートの Config が変えられるような状況であれば、これら以外の防ぐ方法がいくつかあるので、調べてみると面白いかと思います。