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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2412450/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 07:59:22  来源:igfitidea点击:

Git pre-commit hook : changed/added files

githookpre-commit-hookpre-commit

提问by igorw

I am writing a pre-commit hook. I want to run php -lagainst all files with .php extension. However I am stuck.

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

I need to obtain a list of new/changed files that are staged. deleted files should be excluded.

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

I have tried using git diffand git ls-files, but I think I need a hand here.

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

采纳答案by araqnid

git diff --cached --name-statuswill show a summary of what's staged, so you can easily exclude removed files, e.g.:

git diff --cached --name-status将显示暂存内容的摘要,因此您可以轻松排除已删除的文件,例如:

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

This indicates that wt-status.c was modified and wt-status.h was removed in the staging area (index). So, to check only files that weren't removed:

这表明在暂存区(索引)中修改了 wt-status.c 并删除了 wt-status.h。因此,要仅检查未删除的文件:

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

You will have to jump through extra hoops to deal with filenames with spaces in though (-z option to git diff and some more interesting parsing)

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

回答by LarryH

A slightly neater way of obtaining the same list is:

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

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

This will return the list of files that need to be checked.

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

But just running php -lon your working copy may not be the right thing to do. If you are doing a partial commit i.e. just selecting a subset of the differences between your current working set and the HEAD for the commit, then the test will be run on your working set, but will be certifying a commit that has never existed on your disk.

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

To do it right you should extract the whole staged image to a temp area and perform the test there .

要做到这一点,您应该将整个暂存图像提取到临时区域并在那里执行测试。

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

See Building a better pre-commit hook for Gitfor another implementation.

请参阅为 Git 构建更好的预提交钩子以获得另一个实现。

回答by Marian HackMan Marinov

Here is what I use for my Perl checks:

这是我用于 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)

for PHP it will look like this:

对于 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)

回答by eddygeek

None of the answers here support filenames with spaces. The best way for that is to add the -zflag in combination with xargs -0

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

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

This is what is given by git in built-in samples (see .git/hooks/pre-commit.sample)

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

回答by mpersico

git diff --cached is not sufficient if the commit call was specified with the -a flag, and there is no way to determine if that flag has been thrown in the hook. It would help if the arguments to commit should be available to the hook for examination.

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