Git pre-commit hook : changed/added files
Solution 1:
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 -l
on 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.
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 Git for another implementation.
Solution 2:
git diff --cached --name-status
will show a summary of what's staged, so you can easily exclude removed files, e.g.:
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:
steve@arise:~/src/git <master>$ git diff --cached --name-status | awk '$1 != "D" { print $2 }'
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)
Solution 3:
None of the answers here support filenames with spaces. The best way for that is to add the -z
flag in combination with 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)
Solution 4:
Here is what I use for my Perl checks:
#!/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:
#!/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)