Yipit Django Blog: Why You Need a Git Pre-Commit Hook
tech.yipit.com
tech.yipit.com
MIGRATIONS_DIRECTORIES="$(find -type d -iname migrations)"
UNTRACKED_MIGRATIONS="$(git ls-files --exclude-standard --others -- $MIGRATIONS_DIRECTORIES | egrep '(.*)[.]py$')"
if test -z "$UNTRACKED_MIGRATIONS"; then
# If there are no untracked .py files in the migrations directory, do nothing, allow commit.
true;
else
# If there are untracked files in the migrations directory print a warning message.
echo "Warning -- Untracked files in the migrations directory"
echo 'The commit may be forced with "git commit --no-verify"'
echo
echo "$UNTRACKED_MIGRATIONS"
exit 1
fi1) Sometimes (usually the worst times) you just need to check something in, maybe it doesn't pass pep8 but when service is down nobody gives a shit.
2) Instead of promoting thinking and caution it promotes attitude of "hey check it in and see if it sticks".
Post commit hooks that report broken tests, poor code, etc preferable to whole team are far superior. After first couple of times being shamed people will actually look over their code, run tests, run pep8, etc to verify the commit isn't bogus.
Tool I use doesn't have that AFAIK. My comment was focused on universal concept "pre-commit hook" not a particular tool.
First, they're easy to skip with one flag. (But do you really want to be skipping tests when things are already broken? Assuming pre-commit hooks don't take many minutes to run – if they do, I'd consider those hooks too long for a pre-commit – it seems wise to sanity check your emergency commit and help ensure it doesn't make the problem worse.)
Second, having standard sanity/smoke tests run as pre-commit hooks means you can easily run those tests with one command – `git commit` – and not have to worry about either forgetting a test or forgetting to test entirely. Doing those tests as a post commit simply means you've possibly made a record of broken code and you'll probably just rebase before pushing. Doing test post push just means you're wasting others time with your noise or broken code. It's always best to expose problems as early as possible and to keep the influence of those problems as localized as possible.
This isn't to denigrate post push testing. I think it's extremely smart to have long running tests, ideally running on build or test servers, exercise a code base after a push and I think it's may be reasonable to notify many people when those tests fail, depending on the severity and scope of the failure. I just think that making it easy to run sanity/smoke tests and baking that into the infrastructure so it happens quickly and automatically is a smart move as well.
It just runs pyflakes and does some sanity checking. Best of all, it doesn't go around stashing files or otherwise messing with your working directory or repository. It just uses some git plumbing commands to copy the current index (what you're about to commit) to a temporary directory.
I can't remember where I copied it from but it works perfectly, only copying whatever I'm about to commit:
git diff --cached --name-only --diff-filter=ACMR | xargs git checkout-index --prefix=$TMPDIR/ --
I can't say how many times this saved me from leaving a pdb.set_trace() in a view somewhere...A leftover pdb.set_trace() that snuck into production is the exact reason we first added this :)
git checkout-index --prefix=../temp/ --all
work?
[snip]
> You seem to suggest that the index consists of only the files that were modified / added in the commit, which is not the case.
To see that the parent's parenthesis doesn't suggest that, consider that in Git you commit the state of the whole tree and not just the modified / added files. The Git manual puts it this way:
[git commit] Stores the current contents of the index in a new commit along with a log message from the user describing the changes.
EDIT: Sorry, now I see what you mean:
>> only copying whatever I'm about to commit
... while the code actually only copies those files that have changes about to be committed.
https://github.com/lbolla/dotfiles/blob/master/githooks/pre-...
It PEP8-fies and pyflakes .py files and gjslint-ifies .js files. Other actions can be easily added!