2015-08-28 32 views
0

我正在嘗試編寫一個git pre-commit鉤子來檢查在提交之前是否再次修改了使用git add分段的文件。pre-commit鉤子檢查是否再次修改了分段文件

基本上我很感興趣,這些文件

git status --short 
MM test1 
AM test2 

現在pre-commit鉤子看起來是這樣的:

#!/bin/bash 

# git pre-commit hook that checks for staged files that were modified. 

# exit on error 
set -e 

# DOES NOT WORK 
cached=$(git diff --name-only --diff-filter=M) 

# everything is fine 
if ! [[ -n $cached ]]; then 
    exit 0 
fi 

# GNU and BSD versions of xargs behave differently. 
if xargs --version >/dev/null 2>&1; then 
    flag="-l" # GNU 
else 
    flag="-L1" # BSD 
fi 

printf "The following files have been modified after they have been staged:\n\n" 
printf "$cached" 
printf "\n\nYou can stage these changes with:\n" 
printf " git diff --name-only --cached | xargs ${flag} git add\n" 
printf "Aborting commit. Stage the modified files and commit again or skip" 
printf " checking with --no-verify (not recommended).\n" 

exit 1 

的問題是,這個鉤子也拿起修改過的文件,但沒有上演。我將如何調整我的鉤子?

回答

2

要使用git diff做到這一點,你需要兩個通道,一個查找索引(git diff --cached --name-status或類似)增加或修改的文件,另一個發現以來,該指數的版本(git diff --name-status或類似)修改過的文件。

但是你不必這樣做git diff。答案是在你的那句:

基本上我很感興趣,這些文件...

只要運行git status --short(或--porcelain)和grep爲^[AM]M:這些都是您的文件。運行此輸出通過切分狀態部分(cutsed等);那些是名字。

sed命令可以做的匹配,以及切割,比awk重量更輕,所以可能是最好的工具:

git status --porcelain | sed -n 's/^[AM]M //p' 

有一個缺陷:對文件,其中git status檢測重命名或複製操作(最左列中的RC),則可能會錯過某些索引與工作樹的更改。還有D已提交,但M已修正(未刪除)在工作樹中。我不確定你是否關心這些情況。如果是這樣,請仔細閱讀the git status documentation中的詳細信息並相應地修改sed正則表達式。

(有一個單獨的缺陷:如果你在合併中,git status會告訴你有關合並。但是,你不能提交,直到你完成合並,所以我只提到這個如果有人想在預先提交的鉤子以外使用這個相同的想法)。