問題
上週遇到的一個問題是,在 local 開發的時候,為了要加快開發速度,因此需要特別調整檔案裡面的某個值(很可惜的,這個值沒有辦法透過 env 檔案的切換來替代),然而,我又不希望工程師不小心把這個變動也 commit 進去,因此希望能在 pre-commit 的階段就可以先擋下來。
於是我就寫了下面這樣簡短的 shell sciprt 並放在 .git/hooks/pre-commit 裡面
解法
#!/bin/bash
CHANGEDFILES=$(git diff --cached --name-only --diff-filter=ACM)
INVALIDFILES=0
for FILE in $CHANGEDFILES
do
if [[ "$FILE" =~ (app.routing.module.ts|app.module.ts) ]]; then
VALUE=`cat $PWD/$FILE`
if [[ "$VALUE" =~ (foo|bar) ]]; then
echo "DO NOT commit $FILE with foo or bar"
$((INVALIDFILES += 1))
fi
fi
done
if [[ "$INVALIDFILES" > 0 ]]; then
exit 1
fi
exit 0
分解動作
收集有被更動、準備要被 commit 的檔案
CHANGEDFILES=$(git diff --cached --name-only --diff-filter=ACM)
建立一個變數,收集 invalid 檔案的數目。初始值為 0
INVALIDFILES=0
用一個 for loop 來遍歷剛剛收集到的檔案們
for FILE in $CHANGEDFILES
do
...
done
用 if 來判斷這些檔案當中,是否有我們的目標檔案
if [[ "$FILE" =~ (app.routing.module.ts|app.module.ts) ]]; then
...
fi
若有,則先將該檔案的資料讀取出來。這裡的檔案路徑採用 $PWD/#FILE
以取得完整路徑
VALUE=`cat $PWD/$FILE`
接著,如果檔案裡面有我們不想要的值(譬如 foo 或是 bar),那麼就印出警告訊息,同時讓變數 INVALIDFILES
加 1
if [[ "$VALUE" =~ (foo|bar) ]]; then
echo "DO NOT commit $FILE with foo or bar"
$((INVALIDFILES += 1))
fi
最後,如果 INVALIDFILES
大於零,就代表有 invalid 的檔案,所以就用 exit 1
終止執行,檔案也就不會被 commit 進入 git 的紀錄當中。若 INVALIDFILES
為 0,那麼就會執行 exit 0
,讓 commit 順利完成。
if [[ "$INVALIDFILES" > 0 ]]; then
exit 1
fi
exit 0
參考資料
我主要參考《Bash 脚本教程》 變查邊做,不過剛剛也找到一些可以參考的網站: