The index being so visible by default (as opposed to being a behind the scenes thing in most other VCS system) definitely adds some complexity. I need to sit down someday and figure out exactly how the git index fits into everything, because that is the sticking point on the one thing I used to do automatically in Mercurial that I have not figured out how to do in git other than manually.

I had this hook in Mercurial on OS X:

pre-commit = mdfind -0 -onlyin . "kMDItemContentTypeTree = 'com.apple.package'" | xargs -0 hg addremove

For those not familiar with Mercurial, "hg addremove dir ..." adds any files from the specified directory that are not already in the repository, and removes from the repository any files that were from the repository that have been deleted from the specified directory.

For those not familiar with OS X, that mdfind command is finding directories in or under the current directory that have the kMDItemContentTypeTree list in the metadata includes com.apple.package. These are directories that are logically treated as if they are single files.

Suppose I am keeping a TODO list named "TODO" with my project, and I'm using OmniOutliner to organize it. The TODO list will be in a directory named "TODO.oo3". OmniOutliner will keep an XML file in that directory that has most of my TODO list. If all my TODO list consists of is formatted text, that will be all that is in there, and everything is simple. As far as any DVCS goes, I can just treat that XML file as my entire TODO list. It will be no different than a code file, except that I edit it with OmniOutliner instead of vim or TextMate.

Now suppose I add more than just simple formatted text to my TODO. OmniOutliner allows adding files as attachments. They get copied into the TODO.oo3 tree. It also allows recording audio notes, which get stored as files in TODO.oo3. Deleting an attachment in OmniOutliner will delete the file from TODO.oo3.

So what my Mercurial pre-commit hook is doing is finding any files that have been added or removed in directories like my TODO.oo3, and adds any newly added files and removes any deleted files. Files that have just had contents changed will be taken care of by the normal operation of Mercurial.

With git, I'm not sure how to handle this. There are two main issues.

1. Where to handle this. I think the adding and removing of files from the magic directories need to occur on commands that modify the index. In particular, on "add -u". However, I don't see any hook for this. Git's pre-commit hook is, unsurprisingly, for commits, which is too late.

2. Dealing with fancy things like stashes. In general going over ever git command that affect the index and making sure that magic directories are being handled right.

It would be ugly, but I'm starting to suspect it might require putting a wrapper around the git command itself, which is kind of ugly.

Another possibility is a pre-commit hook that just checks to see if any magic directories have added or removed files, and if so aborts the commit and alerts the user that they need to "git add" or "git rm" those files or add --no-verify if they want to commit anyway. It wouldn't be as clean as it was in Mercurial, but it would at least be an improvement over relying on noticing in the "git status" I almost always do before committing that I've got some add/removes in a magic directory that need to be taken care of first.