Fixing git pre-commit hook woes

I’ve had something strange occur when attempting to commit changes to a Git repository located on a flash drive. A pre-commit hook, which is a script Git runs before the git commit command does its thing, prevents me from committing files until I’ve removed whitespace characters from the ends of all the lines in the files. Cleaning out such whitespace is good practice if you’re working on a project and you submit your changes as patches; the patch mechanism has a tendency to barf on lines that contain trailing whitespace.

My problem is that not only am I not working on a project where I submit patches, some of the Rails generators create files that contain trailing whitespace (I’m looking at you, RSpec). When I found that the rake db:migrate task adds trailing whitespace to the schema.rb file, I nearly went ballistic. I’d be okay with keeping the whitespace out of my own code, because I’m just OCD enough to enjoy the exercise, but having to fix code generated by automation tools just pisses me off.

To add to the aggravation, the pre-commit hook didn’t seem to run when I was committing to Git repositories on the hard drive of my Mac. I ran afoul of the hook only when committing to a repository on the flash drive or on my Windows laptop.

I got fed up with it enough today to do a bit of digging into the guts of Git. The pre-commit script is created when git init sets up a new repository, and the script is located in a project’s working directory under .git/hooks. The pre-commit script’s comments indicate that it’s designed to prevent trailing whitespace from getting into files destined for patches. The comments also mention the following:

To enable this hook, make this file executable.

Aha! Now we’re getting somewhere. I checked the file permissions, and sure enough, the file is executable in a repository created on the flash drive. However, it isn’t executable in a repository created on the Mac’s hard drive. Digging a bit deeper, I found that the original copy of pre-commit comes from /usr/local/share/git-core/templates/hooks, where the file is also not executable.

It looks like git init loses the file permissions when it copies everything from the Git templates directory over to the flash drive, thereby resulting in files that have full permissions enabled. This makes sense, given that the flash drive is FAT32-formatted; the filesystem doesn’t support Unix-style execution permissions. My Windows laptop has the same problem.

Finally knowing what causes the problem, I defused it by renaming pre-commit in the templates directory to pre-commit.patching. Now if it’s copied with full permissions, it won’t matter, because Git’s looking for a file named pre-commit. I may at some point need to re-enable the hook if I start submitting patches to someone else’s project, but in the meantime, for the majority of work that I do in my own one-man repositories, I’m no longer bothered by an over-protective pre-commit hook.

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*