Does anyone out there know of a good git hook that will check for binaries on commit and throw an error? I'm trying to prevent binaries from getting committed to my repository, but sometimes people make mistakes.
I don't know of an existing hook, but git already comes with a hook that checks for adding "non-ascii names", as a sample pre-commit hook. This will likely already be in your existing git repositories as
Using that hook as a template and considering the answers to "How to determine if Git handles a file as binary or as text?", you could do something like this (see "git's semi-secret empty tree" for where
EMPTY_TREE comes from):
#! /bin/sh stop_binaries=$(git config --get hooks.stop_binaries) exec 1>&2 if [ "$stop_binaries" = true ]; then EMPTY_TREE=$(git hash-object -t tree /dev/null) # or: EMPTY_TREE=4b825dc642cb6eb9a060e54bf8d69288fbee4904 if git diff --cached --numstat $EMPTY_TREE | grep -e '^-' >/dev/null; then echo Error: commit would add binary files: git diff --cached --numstat $EMPTY_TREE | grep -e '^-' | cut -f3- exit 1 fi fi
git diff --cached to see what would be committed, comparing it all against an initial empty tree. Note that it will reject commits with already-existing (but unchanged) binaries; to make it only reject new or changed binaries, add the
against= logic from the non-ascii-names hook. To reject only new binaries add the
--diff-filter=A argument too.
Fancy this up with additional error-message text if you like. You can reverse the test (instead of having to assert "stop binaries", make it default to stop and you have to set "allowbinaries" to add binary files), etc. And of course you can allow specific directories full of binary files, or whatever, as well, by doing additional filtering on the diff-index output.