Last Updated: February 25, 2016
·
541
· forivall

Only allow `git commit -a` when nothing is staged

So I'm really messy with the command line, and I'll sometimes run a commit -a when I have files staged for a normal commit... yeah, I'm terrible.

Anyways, to prevent that, I delved into the core of git, and extracted the follow git pre-commit snippet. It's a little hacky, depending on the pre-commit being a direct child process of the git binary and then uses procfs to extract the original git arguments. I could base it solely on the GIT_* environment vars, but I'll only need to fix that if it breaks.

Now, git does a bit of magic when doing some (aka. pretty much anything other than normal) types of commit. Git will create a copy of the index, called index.lock (a magical binary file that I don't yet understand), and tell itself to use that, rather than the default index (aptly named index). So, when I need to check if I have files currently staged, I have to unset the GIT_INDEX_FILE environment variable, so that git uses index rather than index.lock.

So here's the result! :

[link to gist]

# don't allow --all when we have staged files. It's usually a mistake
# depends on procfs and won't work through gitaliases
while read -d $'\0' arg ; do
    if [[ "$arg" == -a* || "$arg" == -[b-zB-Z]*a* || "$arg" == '--all' ]] ; then
        if (( $((unset GIT_INDEX_FILE; git diff --cached --name-only)|wc -l) > 0 )) ; then
            echo 'using --all while files are cached. don'\''t do that.'
            exit 1
        fi
    fi
done < /proc/$PPID/cmdline