2015-08-28 52 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会告诉你有关合并。但是,你不能提交,直到你完成合并,所以我只提到这个如果有人想在预先提交的钩子以外使用这个相同的想法)。