[Git-Hook] How prevent merge action !? pre-merge Hook!?
週末收到個需求,希望協助解決個 Git 流程上問題
問題是這樣
Integration分支是 master
且有個 Topic分支 Enhancement, 就如他的名稱,這分支會有許多人merge 功能進去
這個 Enhancement 是暫時測試許多功能的分支
只將自己的功能 merge 到 master ,然後push 是標準流程
但是當有人操作錯誤將 Enhancement merge 到自己的分支再合併到 master
或直接 merge master
push 後就大家飛上天啦 …… XD
好長的前言
釐清問題後
重點為 任何分支不能 merge 到 Enhancement
但是 hook 沒有 per-merge 的這種事件 Orz
原因為
You can not prevent people effectivly from locally merging or commiting on any branch. The only really effective way to prevent people from merging/commiting in a branch is a server side hook.
不能在本地端禁止使用者操作(Merge) 分支,只能server端限制
但是在server 端才檢查實在太費時間(中間可能使用者又經過很次修改)
所以轉個想法為在 Post-merge (merge 完成後)時做檢查
若合併了指定 分支名稱建立備份分支
由於合併有兩種 merge / rebase 所以當觸發其中一種時會進行檢查
並且發現有備份分支後禁止 commit 跟 push (必須先手動解決此問題)
在.git 目錄下 hooks 資料夾下分別建立以下檔案 (osx / win 可用)
post-merge
#!/bin/sh #---------------------------------------------------------- # 檢查是否合併了 Enhancement,建立備份分支 #---------------------------------------------------------- # * Author: 羊小咩 Lamb-Mei # * Update : 2014/12/20 # * Description: 當合併了 Enhancement ,顯示警告跟建立備份用分支 # echo $GIT_REFLOG_ACTION | grep -q "merge Enhancement" >> /dev/null; if [ $? == 0 ]; then #已經合併了不想要的分支 echo "Error 合併包含 Enhancement !!" echo "請立即使用 reset 或 revert 解決此錯誤 !!" #複製原始的狀態 git branch AP_ISSUE_HEAD_bak HEAD^1 git branch AP_ISSUE_Master_bak master^1 else echo "check OK 合併檢查無誤!!!" fi
pre-rebase
#!/bin/sh # #---------------------------------------------------------- # 禁止使用 Enhancement,進行 rebase #---------------------------------------------------------- # * Author: 羊小咩 Lamb-Mei # * Update : 2014/12/20 # * Description: 不允許 rebase onto Enhancement # echo $1 | grep -q "Enhancement" >> /dev/null; if [ $? == 0 ]; then #已經合併了不想要的分支 echo "Error 不能使用 rebase onto Enhancement !!" exit 1; else exit 0; fi
pre-commit
#!/bin/sh #---------------------------------------------------------- # 檢查是否包含 AP_ISSUE* 的分支,禁止 commit #---------------------------------------------------------- # * Author: 羊小咩 Lamb-Mei # * Update : 2014/12/20 # * Description: 含有 AP_ISSUE* 的分支 禁止 commit (為了提早發現問題) # git branch | grep "AP_ISSUE" >> /dev/null; if [ $? == 0 ]; then echo "您分支合併了 Enhancement ,請先解決此問題,能才進行後續動作!!" exit 1 ; else exit 0 ; fi
pre-push
#!/bin/sh # #---------------------------------------------------------- # 檢查是否包含 AP_ISSUE* 的分支,禁止 Push #---------------------------------------------------------- # * Author: 羊小咩 Lamb-Mei # * Update : 2014/12/20 # * Description: 含有 AP_ISSUE* 的分支 禁止 Push # git branch | grep "AP_ISSUE" >> /dev/null; if [ $? == 0 ]; then echo "您分支合併了 Enhancement ,請先解決此問題,能才進行後續動作!!" exit 1 ; else exit 0 ; fi
後記
使用上會有一個缺點
由於 merge 動作進行不會觸發任何hook ,除非merge 選項有新commit 狀態
所以進行merge 是已經成功了,所以才在使用建立備份的分支當紀錄點,跟判斷
但rebase 可以在進行之前就先阻擋掉
以上是目前想到最佳的的解決方式
參考資料
How To Use Git Hooks To Automate Development and Deployment Tasks
https://www.digitalocean.com/community/tutorials/how-to-use-git-hooks-to-automate-development-and-deployment-tasks
prepare-commit-msg 也行吧?
#!/bin/sh
case “$2,$3” in
merge,)
grep “‘test'” $1;
if [ $? ];then
echo ‘#######################################’;
echo ‘### 不要将test分支merge到任何分支!!!’;
echo ‘### 这次冲动merge被钩子及时制止了,’;
echo ‘### 现在需要用git reset –hard ORIG_HEAD来恢复一下代码。’;
echo ‘#######################################’;
exit 1;
fi;;
*) ;;
esac
看起來應該也可以