はじめに
push、怖いですよね。
mainやdevelopにプッシュしてしまったら…と考えただけでストレスを感じます。
これでは精神衛生上良くないので、予防策を講じようと思います。
※bashと.bashrcの説明は省きます。
※例外は考慮していません。
追記
コメントを頂いて知ったのですが、一般的にはフック機能というものを使うらしいです。
リポジトリごとに設定できるのが良いですね。
筆者の環境
環境によっては動かないかもしれないので、私の環境を書いておきます。
Windows 11 Pro + WSL(Ubuntu 22.04.4 LTS)
手順
- git関数の追加
- ブランチの保護
- ブランチの保護を解除
- 保護されたブランチの一覧
- pushの制限
という流れでやっていきます。
1. git関数を追加
git() {}
試しに、git push
でHello World!を出力してみます。
git() {
case $1 in
"push")
echo "Hello World!"
;;
esac
}
実行してみます。
~/hoge: bash
~/hoge: git push
Hello World!
動きました!
動作確認出来たので、pushの部分は削除しておきます。
git() {
case $1 in
- "push")
- echo "Hello World!"
- ;;
esac
}
2. ブランチの保護
ブランチ名を直接条件に追加しても良いですが、
保護されたブランチが増えてくると管理が面倒です。
git protect ブランチ名
で保護出来るようにします。
まず、保護したブランチを保存するためのファイルを作成します。
好きなディレクトリに作成してください。
~/hoge: touch protected_branches.txt
次に、作成したファイルを読み込みます。
protected_branches_file="/hoge/protected_branches.txt"
次に、保護するブランチをファイルに書き出します。
protect_branches() {
for arg in "$@"; do
# 一致する行がない場合
if ! grep -xq "$arg" "$protected_branches_file"; then
echo "$arg" >> "$protected_branches_file"
echo "$arg を保護しました"
else
echo "$arg は既に保護されています"
fi
done
}
最後に、git protect ブランチ名
で保護できるようにします。
git() {
case $1 in
"protect")
shift
protect_branches "$@"
;;
esac
}
実行してみます。
~/hoge: bash
~/hoge: git protect hoge fuga
hoge を保護しました
fuga を保護しました
~/hoge: git protect hoge fuga
hoge は既に保護されています
fuga は既に保護されています
+ hoge
+ fuga
動きました!ファイルも更新されています!
3. ブランチの保護を解除
git protect -rm ブランチ名
で解除出来るようにします。
まず、ファイルから保護を解除したいブランチを除けるようにします。
unprotect_branches() {
for arg in "$@"; do
# 一致する行がある場合
if grep -xq "$arg" "$protected_branches_file"; then
# 行完全一致
sed -i "/^$arg$/d" "$protected_branches_file"
echo "$arg の保護を解除しました"
else
echo "$arg は保護されていません"
fi
done
}
次に、git protect -rm hoge
で保護を解除できるようにします。
git() {
case $1 in
"protect")
if [[ $2 = "-rm" ]]; then
shift
shift
unprotect_branches "$@"
else
shift
protect_branches "$@"
fi
;;
esac
}
実行してみます。
~/hoge: bash
~/hoge: git protect -rm hoge fuga
hoge の保護を解除しました
fuga の保護を解除しました
~/hoge: git protect -rm hoge fuga
hoge は保護されていません
fuga は保護されていません
- hoge
- fuga
保護と解除が出来るようになりました!
4. 保護されたブランチの一覧
git protect -a
で一覧表示できるようにします。
まず、保護されたブランチを表示できるようにします。
show_protected_branches() {
readarray -t protected_branches < "$protected_branches_file"
echo "保護されているブランチの一覧"
# 連番: ブランチ名
# !で添字を参照
for i in "${!protected_branches[@]}"; do
printf "%d: %s\n" $((i + 1)) "${protected_branches[$i]}"
done
}
次に、git protect -a
で一覧を表示できるようにします。
git() {
case $1 in
"protect")
if [[ $2 = "-rm" ]]; then
shift
shift
unprotect_branches "$@"
elif [[ $2 = "-a" ]]; then
show_protected_branches
else
shift
protect_branches "$@"
fi
;;
esac
}
実行してみます。
~/hoge: bash
~/hoge: git protect -a
保護されているブランチの一覧
1: hoge
2: fuga
あとはpushを制限するだけです!
5. pushの制限
まず、指定したブランチが保護されているかを判定できるようにします。
is_protected_branch() {
if grep -xq "$1" "$protected_branches_file"; then
return 0
else
return 1
fi
}
次に、git push 保護されたブランチ名
の場合にメッセージを表示し、pushを拒否します。
git() {
case $1 in
"push")
# "push -f"のようにオプションを付ける場合を考慮して、最後の引数だけ渡す
if is_protected_branch "${@: -1}"; then
echo "このブランチは保護されています"
echo "pushを実行するには、保護を解除してください"
else
command git "$@"
fi
;;
"protect")
# 省略
;;
esac
}
このままだとpushとprotect以外が実行できません。
他のコマンドも実行できるようにします。
git() {
case $1 in
"push")
# 省略
;;
"protect")
# 省略
;;
*)
command git "$@"
;;
esac
}
実行してみます。
~/hoge: bash
~/hoge: git push hoge
このブランチは保護されています
pushを実行するには、保護を解除してください
pushとprotect以外が実行できるかも試してみましょう。
~/hoge: git status
On branch main
nothing to commit, working tree clean
完成です!
pushに怯える日々ともこれでおさらば!
おわりに
初めてbashという言語に触れたのですが、
ifやcaseの終わりがfi, esacになっていて、お洒落だな~と思いました。
参考記事
余談
今回、wsl/Ubuntu/etc/bash.bashrc
を使ったのですが、
- Windowsのbashrc
- WSLのbashrc
- Git for Windowsのbashrc
がPC上に存在していて、最初はどれが適用されているのか分かりませんでした。
bashrcの先頭でファイルパスをechoすると迷わないのでおすすめです。