This page last changed on Oct 27, 2011 by jive.

There has been some recent interest in supplementing our current version control systems with a distributed versioning tool like mercurial or git since they are much better at handling branches. For a few months now I have been using git to manage code locally and wanted to share my findings.

I initially tried out mercurial (hg) but was not completely happy with it. And I have heard that the svn integration can be a bit flakey. So i moved to git and have found it to be very pleasant to work with, especially its svn support.


General workflow

The setup

I will qualify this with stating that the setup I have adopted is a conservative one. Svn support from git goes both ways, you can read from an svn repo and write back to it. But I only use it to read. This is in part influenced by what happened in geotools when someone tried to do this with hg and ended up corrupting the svn repo.

So for that reason I actually maintain two repositories for each geoserver/geotools branch. The first repository is a pure svn repository. The sole purpose of this repository is to commit back into the central subversion repository, i never develop on it.

The second repository is the git/svn hybrid and is where i do my development. Actually it is not an svn repository, it is a git repo but is linked back to the central central svn repo.

So what this looks like is this:

svn co gs_svn
git svn clone gs_git

You can limit the checkout to recent work:

git svn clone -r 16000:HEAD geoserver-trunk

Git does not support svn:externals so we need to make a few symbolic links by hand:

ln -sfn data/minimal src/web/app/minimal
ln -sfn src/web/core/src/main/java/org/geoserver/web/css src/web/app/src/test/java/org/geoserver/wicket/test/css
ln -sfn src/web/core/src/main/java/org/geoserver/web/img src/web/app/src/test/java/org/geoserver/wicket/test/img
ln -sfn data/citewfs-1.1/styles data/citewfs-1.1-h2/styles


The common workflow pattern with a dvcs is to create a branch every time you want to work on a new feature or a bug. This is not much overhead because branches in git are so cheap to create. The main branch is git is referred to as the "master" branch.

So let's say i want to work on a new feature. So I create a new branch in my git repo:

[gs_git] git branch virtual_services
[gs_git] git checkout virtual_services

At this point I am free to work and make modifications.


So after I work for a while I am ready to commit locally to my branch. Here is where git differs a bit from svn. When you commit it is a two stage process. First you must "add" the files you want to commit. And then you commit. Git add essentially "stages" files and flags them for the next commit. Consider two files that have been changed (foo.jar and Committing changes looks something like this:

[gs_git] git add
[gs_git] git commit -m "changed"
[gs_git] git add
[gs_git] git commit -m "changed"

There are ways to make this easier. Let's say I want to commit them both at the same time:

[gs_git] git -a commit -m "changed and"

The "-a" flag allows you to automatically stage/add the files to be committed.

Getting updates

So let's say I have been working on my branch but want to get updates from the central svn repo. Now this is in my opinion is where git really shines via "rebasing". I can update my branch which changes from the central svn repo like this:

[gs_git] git svn rebase

Now the key here is how the update was actually applied to my branch. I won't go really into what rebasing is but essentially what it does is shifts my branch so that it looks like it diverged from the revision i just updated to. The upshot of which is that my branch instead of being a mix of my own commits, and updates from the svn repo, is the latest version of the svn repo with all my local branch changes on top of it (resolving any conflicts of course).

So this makes it trivial to get the patch for just my changes on the branch. And this is what makes the branch maintainance so easy with git.

Committing back

As mentioned before I do not use git to commit directly to the svn repository although it does support it. So I generate a patch from git and apply that to my pure subversion repository. Run tests, etc... and then commit.

Possible setups for GeoServer

There are a number of different setups that could be adopted with the use of a dvcs. This section outlines a few of the options.

Hybrid git/svn

The first setup would be a git/svn hybrid system similar to what I have been using. In this setup there would be a single central svn repository like we have now. But also every developer would maintain a git repository linked back to the central svn repository. Each developers git repository could be public. The benefit of which would be to share branches with one another more easily. This simple diagram illustrates the workflow.

Pure git

An alternative strategy to the first would be to adopt a pure git setup and abandon svn all together. In this setup the central svn repository would be replaced by a central git repository. And similar to the first setup each developer would maintain his or her own clone of that repository, possibly making it public.


I we trust git to commit directly to svn the two setups are essentially the same. If we don't trust git to commit to svn then the first setup is more work as it involves staging patches into a checked out svn repository.

Counter point - Hg

Jody here - I had a negative experience with GIT when uDig looked into the transition. The negative experience was just on the windows+git combination (where you have cygwin or as an option). It really was not the kind of thing I could ask a windows developer to install on their system.

Since that time it sounds like there are more options available including eclipse integration.

There are a couple of good resources for Hg:

In short I am favour of using DVCS and would recommend Hg if we have developers on windows.

Document generated by Confluence on May 14, 2014 23:00