web-dev-qa-db-ja.com

Git pre-commit hook:変更/追加されたファイル

コミット前のフックを書いています。 .php拡張子を持つすべてのファイルに対してphp -lを実行したい。しかし、私は立ち往生しています。

ステージングされた新規/変更されたファイルのリストを取得する必要があります。削除されたファイルは除外する必要があります。

git diffgit ls-filesを使用してみましたが、ここで手が必要だと思います。

58
igorw

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オプションといくつかのより興味深い解析)

47
araqnid

同じリストを取得するためのややきれいな方法は次のとおりです。

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用のより良い事前コミットフックの構築 を参照してください。

86
LarryH

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

for 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

ここでの回答はいずれも、スペースを含むファイル名をサポートしていません。そのための最良の方法は、-zフラグをxargs -0と組み合わせて追加することです

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

これは、組み込みサンプルのgitによって提供されます(。git/hooks/pre-commit.sampleを参照)

8
eddygeek

コミット呼び出しが-aフラグで指定された場合、git diff --cachedは十分ではなく、そのフラグがフックでスローされたかどうかを判別する方法はありません。コミットするための引数を、フックが調査のために利用できるようにする必要がある場合に役立ちます。

0
mpersico