There’s been quite a lot of buzz lately amongst Rubyists (or at least amongst those I follow on Twitter) about the new version control system Git. As Linus Torvalds explained in a Google Tech Talk last May, licensing issues drove him to start work on Git to replace BitKeeper, under which Linux kernel developers had previously operated. Torvalds had three main requirements for the project: it had to be fast, it had to be distributed, and it had to be guaranteed never to lose any data.
For mere mortal developers like me, the most attractive one of these three is the second: Git’s distributed architecture. In practice, the fact that Git is distributed means that you can separate the act of committing your changes from the act of publishing them. With Subversion, and other centralized systems, the only way to get your changes under version control is to push them out to the central server from which all of your collaborators pull. So, if you’ve got a set of changes that make a logical atomic commit, but break the build in a major way, you can’t commit them without disrupting the work of others. Git, on the other hand, lets you make commits on your local machine without pushing any changes out to anyone. The result is that you can make a series of commits as you go that leave the app in whatever state you want — even including creating your own experimental branches for trying out ideas, a process Git makes almost trivially easy — and then when you’re ready to push your changes out into the wider world, you can do so without anyone having to see the mess you made along the way. (A cool side effect of this architecture is that you can commit even if you don’t have network access, for example if you’re on a plane, which is where I wrote most of the code I’m about to tell you about…)
Anyway, as soon as I started using Git myself, I noticed the lack of a tool I use so often I’d stopped even noticing it was there: jchris’s svn_tools plugin. It’s a series of rake tasks for controlling Subversion. It provides a bunch of tasks to do common things like add all existing unrecognized files all the way up to bootstrapping a brand new Rails project into a new checkout. And Git definitely has some bumpy edges that would be nice to abstract out in this same way (like the need to type “git commit -a” for almost every commit and the need to manually tell Git about each new file individually when they’re first being added). So, I set out to write a version of the same library for git, one that could provide some utilities that would speed up everyday activities and, eventually, some more complex macros for doing things like bootstrapping a new Rails project.
I didn’t manage to accomplish that second goal, but I made enough progress towards the first, that I thought it would be useful to throw the project out there to see if one of those feverishly twittering Rubyists busy trying out Git might want to pick it up and run it into the end zone. So, without further ado here it is:
The main tasks of interest are:
– adds all files that need a manual git add
– commits with the -a flag thrown so your new content will actually get committed
– removes the given files (or all files matching a quotation-surrounded pattern if given) from version control
For those looking to develop the library further, a full framework for parsing Git’s response messages is already in place as well as a system for executing Git commands (the design of which is yoinked from the svn_tools project). Bits here and there may be a touch wonky (for example, if you send a pattern to rake git:ignore, git raises an error even though it completes the task successfully).
A note on contributing: The archive of git_tools is itself a Git repository. One of the nice things about Git is that the files containing the versioning info are very compact and portable, so it’s easy to ship around copies of a full repository with its entire history. If you make changes or improvements you’d like to see incorporated, just send me an archived version of the updated repository and I’ll merge them in.