Подтвердить что ты не робот

Git pre-commit hook: измененные/добавленные файлы

Я пишу предварительный фиксатор. Я хочу запустить php -l для всех файлов с расширением .php. Однако я застрял.

Мне нужно получить список новых/измененных файлов, которые поставлены. удаленные файлы должны быть исключены.

Я попытался использовать git diff и git ls-files, но я думаю, что мне нужна рука здесь.

4b9b3361

Ответ 1

git diff --cached --name-status покажет краткую информацию о том, что поставлено, поэтому вы можете легко исключить удаленные файлы, например:

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

Это означает, что wt-status.c был изменен, и wt-status.h был удален в промежуточной области (index). Итак, чтобы проверить только файлы, которые не были удалены:

[email protected]:~/src/git <master>$ git diff --cached --name-status | awk '$1 != "D" { print $2 }'
wt-status.c
wt-status.h

Вам придется перепрыгивать через дополнительные обручи, чтобы иметь дело с именами файлов с пробелами (опция -z для git diff и еще более интересный синтаксический анализ)

Ответ 2

Несколько более простой способ получить тот же список:

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 для другая реализация.

Ответ 3

Вот что я использую для своих проверок 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

для 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

Ответ 4

Ни один из ответов здесь не поддерживает имена файлов с пробелами. Лучше всего добавить флаг -z в сочетании с xargs -0

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

Это то, что дается git во встроенных образцах (см. .git/hooks/pre-commit.sample)

Ответ 5

git diff -cached недостаточно, если вызов фиксации был задан с флагом -a, и нет способа определить, был ли этот флаг вставлен в hook. Это поможет, если аргументы для фиксации должны быть доступны для проверки на крючок.