Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Git pre-commit hook : changed/added files

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

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

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

like image 794
igorw Avatar asked Mar 09 '10 20:03

igorw


People also ask

How are pre-commit hooks set?

Open a terminal window by using option + T in GitKraken Client. Once the terminal windows is open, change directory to . git/hooks . Then use the command chmod +x pre-commit to make the pre-commit file executable.

How do I bypass git pre-commit hook?

Use the --no-verify option to skip git commit hooks, e.g. git commit -m "commit message" --no-verify . When the --no-verify option is used, the pre-commit and commit-msg hooks are bypassed.

Where are pre-commit hooks stored?

The hooks are all stored in the hooks subdirectory of the Git directory. In most projects, that's . git/hooks .


2 Answers

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.

like image 50
LarryH Avatar answered Oct 11 '22 02:10

LarryH


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)

like image 40
araqnid Avatar answered Oct 11 '22 03:10

araqnid