Git pre-commit hook:更改/添加的文件

时间:2010-03-09 20:49:01

标签: git hook pre-commit-hook pre-commit

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

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

我尝试过使用git diffgit ls-files,但我想我需要帮忙。

4 个答案:

答案 0 :(得分:83)

获得相同列表的一种稍微简洁的方法是:

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

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

但只是在工作副本上运行php -l可能不是正确的做法。如果您正在进行部分提交,即只选择当前工作集与提交的HEAD之间的差异子集,那么测试将在您的工作集上运行,但将证明您的工作集从未存在过的提交磁盘。

要做得对,你应该将整个阶段图像提取到临时区域并在那里进行测试。

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

有关其他实施,请参阅Building a better pre-commit hook for Git

答案 1 :(得分:46)

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

你必须通过额外的箍来处理带有空格的文件名(gz diff的-z选项和一些更有趣的解析)

答案 2 :(得分:8)

以下是我用于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

答案 3 :(得分:8)

此处的答案都不支持带空格的文件名。最好的方法是将-z标记与xargs -0

结合使用
git diff --cached --name-only --diff-filter=ACM -z | xargs -0 ...

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