Thursday, March 15, 2007

Git and hooks

Update: See my more recent blog post Git hooks for a more in depth look at Git hooks.

The past few weeks I have started learning Git and this past week started using it for one of my own little project I have been hacking on. It has been a fun experience and once I figured out the basics it went pretty smooth. Here are a few tips that would have been nice to know before I started:

- Don't bother using Cogito, but just use Git directly. Git has matured a lot sense it was first introduced and removing another layer helps to make it less confusing.

- There are a handful of docs all over, but Git introduction/tutorial is the best intro I have seen.

- The equivalent of "svn revert file.cpp" is "git checkout HEAD file.cpp"

- Unlike svn Git wont automatically know what you want to commit, you have to add the file first.

- Git bisect is a handy little thing.

- provides a nice easy place to host mirrors or push locations.

The one thing I haven't figured out how to do is go back and edit older commit messages which you can do in svn.

But the coolest thing about Git has to be the hook functionality. CVS, Subversion, Perforce, and well all revision control systems have hooks, but they are all located on the server side, there are no hooks for the client. With Git because your depot is on the client suddenly any hooks that you add are all run locally. To add a script to Git you place it in .git/hooks/ and modify the appropriate hook such as pre-commit to utilize it. Any time I have ever seen hooks being used before now was for integrating with other project services. KDE has some hooks so you can say that the commit solves a bug and it will automatically e-mail that change to Subversion comes with a script to e-mail the change to someone or presumably a mailing-list. KDE has one that is more advanced, but still follows the basic idea of summarizing the change and letting someone/something know. From time to time in open source projects I have heard developers discuss the idea that the hook system can be used to make sure that no commits break the build by compiling the project with the patch first, but invariably it is never implemented because usually the build would take longer then the average time between commits, or the server is on a slow machine, or that the server for security reasons isn't setup for package building, or that the server doesn't have space, or sometimes devs want to commit broken code. Another common request is that any commit go through a code style tool. At least in KDE this would never fly because the KDE repository covers many project with different coding styles just for starters. Suffice it to say any hook that is put in place has to go through the community and overall very inflexible.

With the repository on my local machine I was quick to take advantage of that fact and added a handful of scripts to my pre-commit to:

- Check that the code in the patch conforms to the code style:
"astyle --indent=spaces=4 --brackets=linux --indent-labels --pad=oper --one-line=keep-statements --convert-tabs --indent-preprocessor "
- Check that the project compiles (In theory it was compiled before committing so this should be quick)
- Check that all the autotests affected by the patch pass

My development machine is a fast machine, no one else will be wanting to commit to the server, and I know my box is properly setup for building the repository. The above hooks usually are very quick and I think whatever delay it causes is worth it in the long run. The personalization of the hooks is what makes it more powerful then the hooks on a server though. For me if the source is already built I am not going to force it to distclean and rebuild while for someone else this might be required. Beyond that I even made a hook that checks what time it was and if it was after 3am then it tells me to go to bed and review the commit in the morning. A hook like that would never get into the KDE repository, but it is something I can have locally. Making quick modification to hooks are not something you would do with them on a CVS server. Hooks in revision control systems generally have been a very inflexible and an underutilized idea.

Dozens more ideas for hooks can be found on Spell check docbooks, validate xml files, check for binary incompatibility, etc. Because most of the time patches are small most tests wouldn't even do anything because they wouldn't be affected (i.e. if no xml file have changed there is nothing to validate).

Once I had it setup and running looking at Subversion is seems unfortunate that there isn't an official way to add client side hooks there too.

Some more links:
Hooks in Git Documentation
Hooks in Subversion Documentation

No comments:

Popular Posts