Using git-svn for JRuby

Here’s a brief overview of how I set up and use git-svn to commit to JRuby.

Initial Setup

If you want the whole history of JRuby, branches and all, just do:

git-svn clone -Ttrunk/jruby -ttags -bbranches --username mental jruby

...which will create the directory jruby and clone the entire repository history into it, then check out a working copy from trunk. I typically just work with individual branches, though. My own initial setup was just to work with trunk:

git-svn clone -Ttrunk/jruby --username mental jruby

You don’t actually need the whole history, but it is occasionally incredibly convenient to have, and once you clone you’re mostly stuck.

My username is actually the same locally as it is remotely, so I didn’t need to use the --username option; I just included it for completeness.

Day-to-day Operation

Before starting, I make sure I’m on the right git branch and have no uncommitted changes. Then I can make sure that I have current version of the mirrored Subversion branch I want to work against (here, remotes/trunk):

git-svn fetch -i trunk
git-rebase remotes/trunk

Then I can just git-commit to my heart’s content. When I’m ready to push my changes back to Subversion, I can just run:

git-svn dcommit -i trunk

If there are any conflicts with new changes in Subversion, it will fail and you will need to fetch and rebase again (resolving the conflicts manually —see the git documentation) before you will be able to commit to Subversion. I usually do this proactively, to make sure that I have a chance to test the commits in their rebased form.

Topic Branches

Sometimes I have a number of things I’m working on at once. In those cases I’ll create a topic branch to work on a feature separately, rather than working in a regular persistent branch like master:

git-checkout -b topic/thingy-feature remotes/trunk

At this point topic/thingy-feature becomes the current branch and the procedure works the same as above. Once I’m done working on the feature I usually switch back to one of the “regular” branches and delete the topic branch with:

git-checkout master
git-branch -d topic/thingy-feature
Combining Commits

If I’ve been working in git for a while without commiting to Subversion, I may have a non-trivial sequence of commits saved up (I tend to commit in small increments as I work), where only the final one really reflects a working state. To collapse them into a single commit before dcommitting, I can fetch/rebase and then do:

git-reset --soft remotes/trunk
git-commit -c ORIG_HEAD

I usually don’t need to do this as I try to integrate frequently with trunk, though.

Merges and Non-Linear History

Linear histories are trivial, but merges and Subversion don’t really get along. This extends to git-svn as well. That’s material for another post, however.