Converting an svn repo to git

I like many others have used subversion in the past and now want to switch to git. The following documents the steps involved and offers several comments to make the process easier.

Prerequisites:
I had to install git-svn on ubuntu xenial:
% apt install git-svn

When running git svn clone I was getting errors from perl. I found the solution online.
Add this setting to your ~/.subversion/servers file if it isn’t there already:
[global]
http-bulk-updates=on

Steps:
Here are the steps I took to convert an svn repo completely to git. We use individual repos for every project to keep the revision numbers local to the project.

First make an authors transformation file by doing an svn log and awk’ing for the authors:
% svn log -q https://server/svn/libirl | grep -e '^r' | awk -F'|' '{print $2}' | sort -u
Edit the authors.txt file and put in the correct emails and commiter names.
The format of the lines is username=”full name” <email address>

Then you can run git svn clone:
% git svn clone https://server/svn/libirl --stdlayout --authors-file=authors.txt ./libirl

Note: git svn clone converts the subversion trunk to git’s master, but it leaves the subversion branches and tags as remote references to the svn repo. We are converting from svn to git so we want them local to this new git repo. We will push the branches and the tags later. Check the remote branches and tags that git svn clone converted with:
% git branch -r > tags
% cat tags
1.0.x
1.0.x-win
1.1.x
1.2.x
2.0.x
tags/1.0.0
tags/1.0.1
tags/1.1.0
tags/1.1.1
tags/1.2.0
tags/1.2.1
tags/1.2.2
tags/2.0.0
tags/2.0.1
trunk

The command to convert each remote tag to local is:
% git tag <tagname> <tags/tagname>

This is easily done with bash and read (grabbing only lines that start with tags/):
% while read line;do
[[ ${line} =~ tags/ ]] && git tag ${line#*tags/} ${line}
done<tags

and then deleting the remote references:
% while read line;do
[[ ${line} =~ tags/ ]] && git branch -r -d ${line}
done<tags

List the remote branches again and store them in a new file:
% git branch -l -r > branches
% cat branches
1.0.x
1.0.x-win
1.1.x
1.2.x
2.0.x
trunk

Now convert the remote branches to local branches (skipping the ‘trunk’ because it has become ┬ámaster):
% while read line;do
[[ ${line} =~ trunk ]] || git branch ${line#*/} ${line}
done<branches

and delete the remote references (note here we remove the trunk from the remote branches):
% while read line;do
git branch -r -d ${line}
done<branches

Listing the local branches shows the result:
% git branch -l
1.0.x
1.0.x-win
1.1.x
1.2.x
2.0.x

% git tag -l
1.0.0
1.0.1
1.1.0
1.1.1
1.2.0
1.2.1
1.2.2
2.0.0
2.0.1

There are no longer any remote references:
% git branch -r -l
%

You can do an svn log in the svn working copy and a git log in the git repo and compare the history.
Add the remote using the name ‘origin’ which is the git default:
% git remote add origin server://path/to/repo.git

Push the repo and any branches to the empty bare repo on your server. –all includes the branches but not the tags:
% git push --all --set-upstream

Then push out the tags:
% git push --tags --set-upstream
Done!
Clone the new remote repo into a different directory to make sure all is well.

Leave a Reply

Your email address will not be published. Required fields are marked *