Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Git预提交挂钩:更改/添加文件_Git_Hook_Pre Commit Hook_Pre Commit - Fatal编程技术网

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

Git预提交挂钩:更改/添加文件,git,hook,pre-commit-hook,pre-commit,Git,Hook,Pre Commit Hook,Pre Commit,我正在写一个预提交钩子。我想对扩展名为.php的所有文件运行php-l。但是我被卡住了 我需要获得一个新的/更改的文件列表。应排除已删除的文件 我尝试过使用git diff和git ls文件,但我想我需要帮忙。git diff--cached--name status将显示暂存内容的摘要,因此您可以轻松排除已删除的文件,例如: M wt-status.c D wt-status.h 这表明暂存区(索引)中的wt status.c已修改,wt status.h已删除。因此

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

我需要获得一个新的/更改的文件列表。应排除已删除的文件

我尝试过使用
git diff
git ls文件
,但我想我需要帮忙。

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
steve@arise:~/src/git$git diff--cached--name status | awk'$1!=“D”{打印$2}”
wt status.c
wt status.h

要处理带有空格的文件名,您必须跳过额外的障碍(git diff的-z选项和一些更有趣的解析)

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

git diff --cached --name-only --diff-filter=ACM
这将返回需要检查的文件列表

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

要正确执行此操作,您应该将整个暂存映像提取到临时区域,并在那里执行测试

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

有关另一个实现,请参阅。

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

#/bin/bash
读取st文件时;做
#跳过已删除的文件
如果[“$st”=='D'];然后继续;fi
#只检查perl文件
如果[[“$file”=~”(.pm |.pl)$“]]&!perl-c“$file”;然后
echo“文件:$file的Perl语法检查失败”
出口1
fi

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

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

这是git内置示例提供的内容(请参见.git/hooks/pre-commit.sample

谢谢,这是一个好的开始。但是,如果我在不暂存文件的情况下更改了文件,它仍然会显示。我正在运行git版本1.7.0.1.147.g6d84b(最近的自定义版本)。不确定这是否是故意的行为。听起来很奇怪。“--cached”开关应使其仅显示已暂存的文件:尽管我正在用1.6.5测试此功能,但令人惊讶的是,这种情况会发生变化。。。“git diff--cached”本身是否显示了未老化的更改?经过一些调试后,我能够跟踪到其他原因。非常感谢@igorw,我很感兴趣,但是链接已经死了。请注意,如果只需要文件名,那么存在--name only而不是--name status。可以减少额外的awk限制。实际上可以将文件内容通过管道传输到
php-l
。这就是我们的结局。请参见此处:要检查暂存文件的语法,您可以使用
git show:FILENAME | php-l
——diff filter可能应该是“ACMR”,因为重命名的文件(R)也可能有更改。非常好,但不适用于部分暂存文件,因为它读取整个文件。谢谢!我修改了你的代码,我把不能再编辑我的评论,所以synthax实际上是,<这很好。但是,它不处理部分暂存的文件。请参阅我对@LarryH's answer.git diff的评论——缓存似乎已经足够了。但是,我相信如果在钩子中运行git status,那么将要处理的所有文件都不会有空白或?在输出的第一个位置。我还没有完全测试过它,但到目前为止,它在我的repo中的所有条件下都有效,我尝试提交显式文件,默认的文件集,一个新的、添加的、修改过的文件的混合体。那么为什么要使用git status而不是git diff呢?我认为它更容易解析。
git status--ceral | grep-E-v'^[?]”
git status--ceral | perl-ane'print$F[1],qq(\n)if m/^[ACM]/'
是一个更好的答案。它的优点是使用一个瓷质选项,保证永不改变。如果perl对您来说太重,请使用您自己的解析器