Experimenting with GIT and Subversion

Written October 18th, 2011 by

In the past few weeks I have experimented with a new workflow based on GIT and Subversion. All our projects are using subversion as version control system, we think that at this time a centralized version control system better suits our needs, however some GIT features maybe very useful to individual developers so I started to investigate on how to take the best of both worlds and integrate GIT in our Subversion-based workflow.

GIT is a distributed version control system, this means that each developer receives a full copy of the repository, so the first think to do is to create a clone of our repository with GIT. Looking around with Google I found that this is a very simple operation:

[marco@bridge git] git svn init -s <svn.repository.url>
[marco@bridge git] git svn fetch

The first command creates a local GIT repository in the current directory and links it to the remote Subversion repository. The second command clones the Subversion repository in the local GIT repository. It may take from few minutes to several hours, depending on the size of the remote repository, but at the end we’ll have a full copy stored in the GIT repository with branches and tags:

[marco@bridge git] git branch -a
* master

The master branch is the one linked with the remote Subversion trunk folder. Each commit done on the master branch will be sent to Subversion with:

[marco@bridge git] git svn dcommit

From time to time you also need to get the latest changes from Subversion and update your local GIT repository. Again this is a very simple operation:

[marco@bridge git] git svn rebase

Make sure you are on the master branch and that it is clean, without uncommitted changes, otherwise rebase will not work. The git stash command is very useful in this case, it allows to temporarily move away the current changes without creating a new commit.

Working on the master branch is not different than working directly on a Subversion working-copy, except you have one additional step (dcommit) to do before your changes are sent to the centralized repository. This may actually be an advantage since you can review your commits and use those nice GIT tricks like interactive rebase and amending to clean the commit history.

The main advantage to use GIT however comes with local branches, so I changed my workflow to create a local branch off of master whenever I start working on a feature, commit changes as needed to keep track of progresses, test the code, commit fixes, etc. Then when I’m satisfied I’ll merge the branch back to master and send the changes to Subversion with dcommit. Merging is where GIT shows its usefulness. A simple merge will replicate all commits from the local branch to master and consequently on Subversion, polluting the remote history with all local commits, however a merge squash will replicate all changes from the local branch without committing, this allows to do a final review of the changes, fix issues due to merging with more recent code, and commit everything as a single commit. The remote Subversion history will then be clean of all local commits and will show just a single changeset with all changes done on the local branch.

The workflow then is:

  1. Create a local branch
  2. Work on the local branch committing as needed
  3. Switch back to master, update from remote Subversion and merge squash from the local branch
  4. Review code, commit and send to Subversion

So far this GIT-Subversion workflow works fine. The development tools supporting GIT however doesn’t support the Subversion integration, so the command line tools are needed most of the times. EGit, the Eclipse GIT integration, is useful to manage the local repository but it is still immature and doesn’t offer all the options available from the command line tools. Hopefully it will offer a more complete integration in the future.