We've got this repo for all our Puppet configs. I wrote the following to validate any changed .pp files and bail out of the commit if validation fails. The pre-commit script runs properly when triggered by git commit
but git commit -a
seems to skip the hook altogether. We use git commit -a
exclusively so this behaviour is a bit of a deal breaker.
Am I doing something wrong? Alternatively, what could I do to duplicate git commit -a's behaviour in the pre-commit script?
#!/bin/bash
# check puppet files for errors before pushing to repo
for name in `git diff --name-only`; do
if [[ $name == *.pp ]]; then
path="$(pwd)/$name"
puppet parser validate "$path"
r=$?
if [ $r -ne 0 ]; then exit 1; fi
fi
done
Pre-commit hooks run on every commit, even when the -a option is specified. Confirm it by creating this script:
#!/bin/bash
echo "Running"
Put the script into .git/hooks/pre-commit
, editing and staging a file, and then:
$ git commit -am "Commit"
Running
[master f042adf] Commit
1 file changed, 1 insertion(+), 1 deletion(-)
git diff
by default diffs against unstaged changes. For example, edit README.md then:
$ git diff --name-only
README.md
$ git add -A
$ git diff --name-only
$
Once the changes had been staged, they no longer appeared in git diff
.
The -a option on git commit
stages the changes before executing the pre-commit hook. For example, if we change our pre-commit hook to this:
#!/bin/bash
echo "Running"
git diff --name-only
Edit README.md
again, then:
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: README.md
no changes added to commit (use "git add" and/or "git commit -a")
$ .git/hooks/pre-commit
Running
README.md
$ git commit -m "Commit"
Running
README.md
On branch master
Changes not staged for commit:
modified: README.md
no changes added to commit
The changes showed up in the diff output, but were not committed. But:
$ git commit -am "Commit"
Running
[master a357465] Commit
1 file changed, 1 insertion(+), 1 deletion(-)
This time, using the -a option, the changes did not show in the diff output (because they were on the stage) but they were committed.
So add the --cached
option to the git diff
command:
#!/bin/bash
echo "Running"
git diff --name-only --cached
Then, after making another change toREADME.md
:
$ git commit -am "Commit"
Running
README.md
[master eaab554] Commit
1 file changed, 1 insertion(+), 1 deletion(-)
The answer is the --cached
option on git diff
.