Using Git with SVN

Author: John Reese

Author’s Note! This tutorial assumes that you are working from a Linux or Unix-like environment, and that you have a general understanding of version control concepts. If you are working from Windows, you will currently need to install Cygwin or a virtual machine with a Linux or Unix-like operating system, as there is no official or stable Git client yet available for Windows.

Note by Giallu: It seems this is changing and there is a MinGW/MSYS port in the works, with binaries available

Now that Mantis has switched to a Subversion repository, it is possible to use the Git distributed version control software to:

  • access the Mantis repository
  • maintain a local mirror of the entire Subversion tree
  • branch and commit changes in a local environment without affecting the Subversion tree
  • share branches and changes between other developers using Git
  • push committed changes back to the official repository

By using Git, you will have the freedom to work on your local mirror of the repository, make changes to it at will (even if you don’t have commit access to the real repository), and easily share your changes for others to use or work from.

Getting Started Learning Git

It is highly recommended that anyone interested in Git (who has previous experience with version control software) watch this presentation by Randal Schwartz, "What Git Is". It introduces the concepts underlying Git and how it works. If you are new to version control in general, or if you would prefer to read more about Git, you should check out the Git Crash Course index.


In order to access a Subverson repository with Git, you will need to install Git and the git-svn tool. If you download and compile the Git tarball directly from the Git website, git-svn will be compiled along with the core application. Directions for building can be found in the tarball contents, and will not be discussed here.

Most Linux distributions, however, keep git-svn in a separate package from the primary application. For Debian- or Ubuntu-based linux distributions, the following command will install Git and git-svn:

$ sudo apt-get install git-core git-svn

For Fedora-based distributions, the following command should be used:

$ sudo yum install git-core git-svn

Note: Red Hat Enterprise Linux (and clones like CentOS) does not have those packages in the default repositories, but they can be easily found in third party ones.

A (incomplete) list follows (please pick only one, as mixing repositories is known to be dangerous):


Once you’ve installed Git and git-svn, check your installation by configuring your account with Git.

$ git config --global "<Your Name>"
$ git config --global "<Your Email Address>"

This will set the name and email associate with commits in Git. This is important because you want you changes actually attributable to yourself, unless you like being anonymous.

If you are using a terminal that supports colors (you most likely are), then you can configure Git to show colors for different commands, which makes some things easier to read and visualize:

$ git config --global color.branch "auto"
$ git config --global color.diff "auto"
$ git config --global color.status "auto"

Then, if you are used to CVS/SVN commands, you may want to set some aliases:

$ git config --global commit
$ git config --global checkoutChecking Out

Author’s Note: You will generally need about 300 megabytes of free space during the process, but when you’ve finished this process, the repository should take up less than 40 megabytes.

Now you’re ready to mirror the Mantis Subversion tree to a local, isolated working area. Starting from our home directory, we’ll create a workspace directory, and then ‘clone’ the the relevant (1.0.0, 1.1.0, and 1.2.0) portions of the Subversion tree into a fresh Git repository:

$ mkdir workspace
$ cd workspace
$ git-svn clone \
--trunk=trunk/mantisbt --tags=tags \
--branches=branches --revision 4152:HEAD

Note: If you are using cygwin and you get an error relating to, see this blog entry for the solution. If you are using Fedora 8 and you get an error relating to, “sudu yum install perl-Error”. This is caused by a known bug.

Note: If you are using cygwin and you get the following error: “fatal error - unable to remap C:\cygwin\..... to same address as parent(0×1030000)”, see Unable to remap - Basically close cygwin console window, run “ash” from the cygwin bin folder, and run “/bin/rebaseall” in the opened console window.

At this point, Git will begin communicating with the Subversion server, fetching individual revisions one-by-one and storing them in its local repository. This will likely take a long time, as there are about 800 revisions to fetch at the time of writing. Either work on something else in the meantime, or enjoy watching revision info fly up the screen as Git does its job.

It’s done now? Great! We may have a mirrored repository now, but we’re not done yet. We need to normalize our repository, set up a couple basic branches, and then ‘garbage collect’ to reduce the size of our workspace.

First, we’ll need to make sure our branches are set up right. We’ll do this with the git-branch command, which we use for both looking at and selecting available branches. The first command will show local branches, and there should be only one, ‘master’. The second command will show ‘remote’ branches from the Subversion server, including tags, and this should show all of them. If this does not show any remote branches, something went foul, and you will need to start form scratch.

$ git branch
$ git branch -r

Now, the ‘master’ branch will already be selected, and we can confirm this by running:

$ git status

However, because of the way git-svn works, the ‘master’ branch may be following different remote branches based on the latest remote commits, so let’s set up some better named branches that we can use. We’ll start by simultaneously creating and checking out a local ‘trunk’ branch that will follow the remote ‘trunk’ branch:

$ git checkout -b local-trunk trunk

Now, we’ll create (but not checkout) local branches following important remote branches (currently the 1.1.0 branch):

$ git branch local-branch_1_1_0 BRANCH_1_1_0

And we no longer need the ‘master’ branch, so we’ll get rid of that to reduce confusion and disk-usage:

$ git branch -D master

Finally, we’ve got our branches set up, so it’s time to run ‘garbage collection’ on our repository, so Git will compact or remove unneeded files:

$ git gc

And that’s it! Your Git repository is now a local mirror of the Mantis SVN repository. You’ve set up your branches, and you’ve compacted your repo to better utilize disk space. In the next section, we’ll discuss how to maintain your local mirror: how to fetch updates from SVN, merge or ‘rebase’ your changes onto those updates, and send local changes back to the server. Later, we’ll discuss how to share local changes with other developers without committing to the server, and some best practices for using Git.

Git-SVN Workflow

Author’s Note: this section assumes that you have learned your way around Git and have already started making some changes.

Update From Server

When revisions have been committed to the Mantis SVN server, your local Git repository will need to be told to look for and retrieve those changes:

$ git-svn fetch

However, this will only update the repository’s knowledge of the remote branches. You local branches will not be affected, and you will need to specify how you want those changes to be replicated in your local branches. You actually have two options with Git, unlike most other source control tools that only offer a straight ‘merge’.


This is the preferred method for integrating remote changes into your local branch. Git will take your locally-unique changes, and ‘replay’ them onto a fully-updated version of the branch. This creates a much nicer, linear history, as compared to a ‘merge’.

If you are working on a local branch that directly follows a remote branch, you will need to:

$ git-svn rebase

Otherwise, on a branch following another local branch, you will use the generic version:

$ git rebase

Conflicts may occur if a remote change is very near, or on the same line as, your changes. If this happens, Git will let you know what files are in conflict (also seen by git-status after the failed rebase). You will need to manually edit the files to find and resolve the conflicts, and remove the extra symbols/lines pointing out the conflict. After you have saved the resolved file(s), you will need to tell Git that you have resolved the files, and to continue the rebase:

$ git add <filenames>
$ git-svn rebase --continue
$ git rebase --continue

If there are too many conflicts, and you want to go back to where you were:

$ git rebase --abortMerge

If a ‘rebase’ doesn’t work out, or if you only want to integrate specific changes form one branch to another, you will need to use the ‘merge’ technique. Instead of creating a single, linear history, ‘merge’ will create a more varied, but more flexible history, preserving timestamps. This is generally only recommended for use between two local branches for local changes only.

As this is a much more complicated procedure, you should read the man pages for git-merge and git-cherry-pick to learn more about how these commands work, and how to use them.

Commit to Server

Author’s Note: This section assumes you have been granted commit access to the Mantis SVN repository. If you do not have commit access, then you may be interested in Sharing Branches with other developers, or Getting your Patches into Mantis.

Once you have committed changes to a local branch, you will need to take further steps to transfer those changes to the actual Subversion server. This process is mostly automated, but the difficulties arise from getting your changes in the right place and the right frame before letting the automation take over.

For the purpose of conveying the ideas of this topic, this section will assume you have three local branches in your Git repository: local-trunk which follows the remote branch trunk, plus new-feature and bug-fix, both of which follow the aforementioned local-trunk branch. For the sake of simplicity, this section will assume that both branches have independent changes with no major conflicts, and the entire changesets from both branches are to be committed to the SVN server.

Preparing Your Branches

The first order of business when pushing changes to the server is to prepare your local branches. This is crucial in making sure that your changes will not break either the working tree on the server or your local repository.

We will start by updating our local repository with the latest changes from the server. This is covered in full in the section above, but we will cover the commands to run here to reinforce the concept. If there are any merge conflicts during this process, you will need to resolve them before continuing further.

First we’ll update local-trunk which is following the remote branch trunk:

$ git checkout local-trunk
$ git-svn rebase

Now we’ll make sure the latest changes are in both of our local working branches, bug-fix and new-feature:

$ git checkout bug-fix
$ git rebase local-trunk

$ git checkout new-feature
$ git rebase local-trunk

All three branches should now be up to date and ready for the next step; you can verify this by running git-log on any of the branches and checking to make sure that the latest SVN commits are in the branch history.

Merging Your Branches

Now we will begin merging our changes from the new-feature and bug-fix branches into the local-trunk branch, and double check everything before we start committing the changes to the server.

There are multiple ways to merge everything, which you can read about in the Git manpages and elsewhere online, but for the sake of both simplifying the process and reducing the number of upstream commits, we will squash our local branch merges into single revisions in local-trunk.

First, we will merge the changes from the bug-fix branch and commit them to local-trunk as a single revision:

$ git checkout local-trunk
$ git merge --squash --no-commit bug-fix
$ git commit -a

Now we’ll update the new-feature tree and merge it in the same way as before:

$ git checkout new-feature
$ git rebase local-trunk

$ git checkout local-trunk
$ git merge --squash --no-commit new-feature
$ git commit -aCommitting the Changes

Now that our local-trunk branch has the necessary revisions merged from our local branches, we’re ready to push our changes back to the SVN server:

$ git-svn dcommit

Our code has now been committed to the SVN server, and our Git repo has been updated to have the appropriate revisions in local-trunk marked with the SVN revisions. If we want, we can continue working from the local new-feature and bug-fix branches (after rebasing both, of course), or we can move on to the next session to clean up our repository.


Assuming that work in the new-feature and bug-fix branches is now completed, we can delete these branches from our local repo, to keep it cleaner and use less space:

$ git checkout local-trunk
$ git branch -D bug-fix
$ git branch -D new-featureShare Branches Misc. Notes
  • To commit from git to svn, use the following command:
git-svn dcommit

Note: If you get a Perl error about Term/ not found, you can use the following commands on Fedora:

su (to run the following commands as super user)
yum install perl-TermReadKey
  • To generate a patch with all accumulative changes made on a branch (i.e. changes already committed to the branch):
git diff local-trunk..feature-branch > feature_patch.diffGit resources on the web