Git and SVN: Happily Ever After?

motif

Developers are interesting creatures – curiosity and the urge to explore are their second nature. The way it goes today (until quantum computers replace everything 😉 ) we still need to share our findings in some way, which happens to be a code repository. For years, Mule has been using Subversion (and CVS before that), and today there are new kids on the block fighting for our attention. While we aren’t yet ready to make a full switch (infrastructure tools need to mature, non-developers need some training, etc.), we’re happy to play with . Lucky us, they came up with a way to marry two worlds, which gives Subversion a ‘lease extension’.

This post describes a workflow which worked quite nicely for us. Who knows, maybe it helps your organization keep developers happy, while preserving sysadmin’s good night sleep too? Post your findings in the comments.

This article is also available on-line in Mule’s Developers Resources.

Prerequisites

  • Subversion is installed
  • Git is installed
  • git-svn optional module is installed

Details of obtaining and configuring those are out of scope of this post, just Google it 🙂

Assumptions

  • cross-branch merging is done only via svn, use a dedicated pure-svn checkout for svnmerge operations
  • Checkout only a single branch via git-svn. Need a new branch from svn? Do another checkout in a separate directory. This will save you a world of pain.
  • Private branches are forked off this single git-svn branch. One can have as many as he wants. The difference is all pushed commits end up in a single public svn branch.
  • Ensure there is a backup strategy for the git checkout directory. As it is all file-based, it’s trivial to setup. Remember that private branches are not stored anywhere on the server, any HDD failure ‘oops’ becomes your responsibility.
  • There are some rules to follow (outlined below). Certain git commands should not be tried on this special git-svn checkout.

Workflow

Let’s assume we want to use the mule-3.x svn branch for our git-svn bridge. Initialize with this command:

Note how a starting revision is specified – don’t go overboard checking out from revision 1 – doesn’t make any sense and takes forever. I found that around 2000 revisions is more than enough to dig through history.

Type:

There should be a single branch master marked with an asterisk (for current branch).

NEVER work on this master branch directly. The reasons are numerous, without going into details just treat it as a 1-to-1 replica of the svn branch state, and make sure it stays like that. SVN branches are cheap, but Git branches are beyond cheap, so you have no excuses.

Create a branch for a feature/fix/anything:

This is a shortcut notation telling git to create a new branch, ‘mybranch’, and immediately check it out.
Just for demo purposes, type:

and notice there are 2 branches now, ‘master’ and ‘mybranch’, with the latter being active (asterisk next to it).

Now hack away, use standard git commands to commit.

When you are ready to push it back to a public SVN repository:

Important points here are:

  • Commit from the branch you made changes to (mybranch, not master)
  • Every change you made to this branch is pushed out. There’s no way to cherry-pick commits to push out this way. However, if you need anything like that – just create a new git branch from some point in time, cherry-pick changes into this one-off branch and ‘git svn dcommit’ from there.
  • Commits go to the origin branch, which in this case is mule-3.x in SVN.

Advanced Workflow

Rebasing is one of the most important operations you’ll get to know and love when working this way. For SVN converts this is very similar in nature to an ‘update’ operation on your working copy:

  • Your work dir must be clean (no uncommitted changes) – learn git stash/pop as a trivial solution to this.
  • Local changes are rolled back, updates are pulled from remote SVN, local changes ‘replayed’ back onto the current state of the codebase. If you do rebasing regularly, this will never cause any conflicts and be a smooth ride.
  • It is possible to rebase in any ‘feature’ branch, just make sure any branch is up-to-date (rebased) when you start working with it.
  • There’s no reason to keep branches around once done – hack/commit/delete and move on.

We'd love to hear your opinion on this post


2 Responses to “Git and SVN: Happily Ever After?”

  1. One thing to note: Maven’s Build Number plug-in chokes on Subversion repositories checked-out via Git because it can’t get the revision number out of it.

    In Mule’s Maven parent POM, we solve this by allowing the deactivation of the plug-in via the deactivation of a specific profile. See: http://gist.github.com/467020 for the exact implementation.

  2. I’ve just statically disabled the buildnumber plugin for now via $MAVEN_OPTS: -Xmx512m -XX:MaxPermSize=256m -DskipBuildnumber=true

    There are some patches submitted for this plugin to natively support Git, until then, I can live with current one.