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

igo*_*orw 61 git hook pre-commit pre-commit-hook

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

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

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

Lar*_*ryH 89

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

git diff --cached --name-only --diff-filter=ACM
Run Code Online (Sandbox Code Playgroud)

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

但只是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
Run Code Online (Sandbox Code Playgroud)

请参阅为Git构建更好的预提交挂钩以用于其他实现.

  • 实际上可以将文件内容传递给`php -l`.这就是我们最终的结果.见这里:http://github.com/phpbb/phpbb3/blob/develop-olympus/git-tools/hooks/pre-commit (4认同)
  • --diff-filter应该是"ACMR",因为重命名的文件(R)也可能有变化. (4认同)
  • 要检查暂存文件的语法,可以使用`git show:FILENAME | php -l`. (2认同)

ara*_*nid 48

git diff --cached --name-status 将显示已上演的内容摘要,以便您轻松排除已删除的文件,例如:

M       wt-status.c
D       wt-status.h
Run Code Online (Sandbox Code Playgroud)

这表明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
Run Code Online (Sandbox Code Playgroud)

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

  • 仅当文件名不包含空格时,awk 命令的“print $2”部分才能正常工作。对此的一种可能的解决方法是:`... | awk '$1 != "D" { $1=""; 子(FS,“”);打印 $0 }'`。另请注意:对于文件重命名,“git diff”命令会打印旧名称和新名称。如果只需要新名称,请在“git diff”中添加“--no-renames”选项,这会将重命名视为删除旧文件并添加新文件。 (2认同)

小智 10

这是我用于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
Run Code Online (Sandbox Code Playgroud)

对于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
Run Code Online (Sandbox Code Playgroud)

  • 非常好,但不适用于部分暂存的文件,因为它读取整个文件. (2认同)

edd*_*eek 8

这里没有任何答案支持带空格的文件名.最好的方法是添加-z标志与xargs -0

git diff --cached --name-only --diff-filter=ACM -z | xargs -0 ...
Run Code Online (Sandbox Code Playgroud)

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