Git pre-commit hook: измененные / добавленные файлы - PullRequest
58 голосов
/ 09 марта 2010

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

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

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

Ответы [ 5 ]

85 голосов
/ 18 июня 2010

Немного аккуратный способ получить тот же список:

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

46 голосов
/ 10 марта 2010

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

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

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

10 голосов
/ 06 ноября 2010

Вот что я использую для проверки 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
8 голосов
/ 20 февраля 2017

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

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

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

1 голос
/ 10 сентября 2015

git diff --cached недостаточно, если вызов commit был указан с флагом -a, и нет способа определить, был ли этот флаг брошен в ловушку. Было бы полезно, если бы аргументы для коммита были доступны хуку для проверки.

...