Thursday, May 7, 2009

Git-a-bit - How Git can be useful when being tied to Subversion

There's been a lot of talk lately about the new distributed version control systems like Mercurial, Bazaar or Git. It feels like just yesterday we started the fight to convince the world to switch from CVS to Subversion, and hopefully most of us won. But now more and more projects and even companies are switching to one of the new SCM systems, which might make one both consider why they do so and if one would have to undergo all that pain of convincing and migrating again if the concept looks appealing.

Distributed version control systems offer many advantages. They support offline working without the need of large feature cumulating commits when going back online again, which might be the first usecase people see and understand easily. But scratching the surface a bit, it reveals that there is a lot more, like ultra powerful (of course distributed) branching and merging facilities enabling new development team workflows such as continuous integration per developer/pair, enhanced environments for subteam or featureset driven branches, and a lot more.

Let's say you got intrigued by the features and the advanced workflows those new systems offer and you might have decided to give Git a try because you heard that your IDEA IDE now supports full Git integration, and you are convinced that Linus is a cool guy - what next? Move your or your companies' repositories to Git? Even more complicated, if you are a freelancer or consultant like I am, convince all your customers that this is the next cool thing and they have to switch immediately?

A scenario I recently experimented with came up when I was thinking about a feasible process to enable a local CI infrastructure for experimental changes on the Struts 2 codebase. While we have our central CI builds set up, they mostly make sense for features which are targeted for soon to integrate improvements, unless you are working on a fresh early branch like upcoming version 2.2. You would not want to push highly experimental code that might break builds for a longer time or even might never make it into a release to the upstream repository. Nevertheless, when your experiments turn out to be both stable and useful, you would want to push them as a whole to the main repository.

The solution I came up with was to use git-svn locally, which is not only able to make a git repository mirror out of a svn repo, but also to push changes back to the original svn repository. It helped me to introduce a very useful workflow, allowing me to commit small changes to my local git repository, triggering a local Hudson build, while I go over to the next change. I'm also able to pull incoming svn changes easily, improving the quality of the local integration test and solve merge issues upfront. After implementing and testing all changes, the commit to the svn repository then goes as a whole.

I started to build the Git mirror infrastructure from scratch, without knowing the concise Apache documentation on that topic which Don Brown pointed me to later. The only downside for my boilerplate solution was that since our svn tree is part of the huge Apache svn repository containing all revisions of all projects, the initial creation of the git-svn repo took about one (!!) day - it scanned about 7.3 million revisions only to get our "small" tree synced. But once done, things ran very fast, and getting the local infrastructure with Hudson and IDEA Git up and running was just peanuts.

After all, I found this workflow also very useful for my clients' projects, both for having a CI infrastructure set up even when the client refuses to and to have a good offline working infrastructure in place.


Labels

howto (4) java (3) appclient (2) ejb (2) glassfish (2) jee6 (2) maven (2) netbeans (2) scm (2) tutorial (2) adp1 (1) android (1) announcements (1) cdi (1) dependencymanagement (1) deployment (1) eclipse (1) extusb (1) fluff (1) g1 (1) git (1) htc (1) jee (1) jsr299 (1) liferay (1) m2eclipse (1) miniusb (1) operations (1) plug (1) portlet (1) servlet (1) struts2 (1) svn (1) tomcat (1) windows (1)