84

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

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

我曾尝试使用git diffand git ls-files,但我认为我需要帮助。

4

5 回答 5

104

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

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

有关另一种实现,请参阅为 Git 构建更好的预提交挂钩

于 2010-06-18T10:53:24.870 回答
57

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

您将不得不跳过额外的环节来处理带有空格的文件名(git diff 的 -z 选项和一些更有趣的解析)

于 2010-03-09T22:39:43.900 回答
21

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

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

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

于 2017-02-20T13:05:15.077 回答
16

这是我用于 Perl 检查的内容:

#!/bin/bash

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 < <(git diff --cached --name-status)

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

#!/bin/bash

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 < <(git diff --cached --name-status)
于 2010-11-05T23:45:06.007 回答
0

如果使用 -a 标志指定了提交调用,则 git diff --cached 是不够的,并且无法确定该标志是否已被抛出钩子。如果提交的论点应该可供钩子检查,这将有所帮助。

于 2015-09-10T17:16:44.560 回答