Git预提交钩子:更改/添加文件

我正在写一个预先提交的钩子。 我想运行php -l对所有扩展名为.php的文件。 但是我卡住了。

我需要获取新的/更改的文件列表。 应该排除已删除的文件。

我已经尝试使用git diffgit ls-files ,但是我想我需要一个手在这里。

git diff --cached --name-status会显示出什么内容,所以你可以很容易地排除被删除的文件,例如:

 M wt-status.c D wt-status.h 

这表明wt-status.c被修改,wt-status.h在暂存区(索引)中被删除。 因此,只检查没有被删除的文件:

 steve@arise:~/src/git <master>$ git diff --cached --name-status | awk '$1 != "D" { print $2 }' wt-status.c wt-status.h 

你将不得不跳过额外的箍来处理文件名中的空格(-z选项git diff和一些更有趣的parsing)

获得相同列表的稍微整洁的方式是:

 git diff --cached --name-only --diff-filter=ACM 

这将返回需要检查的文件列表。

但是在你的工作副本上运行php -l可能不是正确的事情。 如果你正在做一个部分提交,也就是只select当前工作集和HEAD之间的差异子集,那么testing将在你的工作集上运行,但是将会validation一个从未存在的提交磁盘。

要做到这一点,你应该把整个阶段的图像提取到一个临时区域并在那里进行testing。

 rm -rf $TEMPDIR mkdir -p $TEMPDIR git checkout-index --prefix=$TEMPDIR/ -af git diff --cached --name-only --diff-filter=ACM | xargs -n 1 -I '{}' \bin\echo TEMPDIR/'{}' | grep \\.php | xargs -n 1 php -l 

请参阅为其他实现构build一个更好的Git预提交钩子 。

以下是我用于Perl检查的内容:

 git diff --cached --name-status | while read st file; do # skip deleted files if [ "$st" == 'D' ]; then continue; fi # do a check only on the perl files if [[ "$file" =~ "(.pm|.pl)$" ]] && ! perl -c "$file"; then echo "Perl syntax check failed for file: $file" exit 1 fi done 

对于PHP,它将看起来像这样:

 git diff --cached --name-status | while read st file; do # skip deleted files if [ "$st" == 'D' ]; then continue; fi # do a check only on the php files if [[ "$file" =~ ".php$" ]] && ! php -l "$file"; then echo "PHP syntax check failed for file: $file" exit 1 fi done 

这里没有答案支持空格的文件名。 最好的方法是将-z标志与xargs -0组合在一起

 git diff --cached --name-only --diff-filter=ACM -z | xargs -0 ... 

这是git在内置示例中给出的内容(请参阅.git / hooks / pre-commit.sample

如果使用-a标志指定提交调用,那么git diff –cached是不够的,而且无法确定该标志是否已经被挂起。 如果提交的论据应该可用于检查,这将有所帮助。