Suppose you have a SVN repository and you would like to move to GIT - there might be many arguments around this. Well - here are some steps that I have tried to synthesise after many attempts and reading in internet. I am sure there are many approaches, but this one works for me straight forward.

The whole procedure consists of several steps:

  • Extracting users from SVN and creating a mapping file SVN_USER <-> GIT_USER
  • Cloning SVN repository into GIT repository
  • Migrating branches
  • Migrating tags
  • Creating new GIT detached repository and pushing all changes to it

Here are some assumptions:

You will work in one directory, where you will create

`Suppose you have a SVN repository and you would like to move to GIT - there might be many arguments around this. Well - here are some steps that I have tried to synthesise after many attempts and reading in internet. I am sure there are many approaches, but this one works for me straight forward.

The whole procedure consists of several steps:

  • Extracting users from SVN and creating a mapping file SVN_USER <-> GIT_USER
  • Cloning SVN repository into GIT repository
  • Migrating branches
  • Migrating tags
  • Creating new GIT detached repository and pushing all changes to it

Here are some assumptions:

You will work in one directory, where you will create

YOUR_SVN_REPOSITORY_URL - is the URL that you use to checkout from SVN.

Lets start

_Extracting users from SVN and creating a mapping file SVN_USER <-> GIT_USER_

GIT needs to know how to map users from SVN to it’s format. Usually users in SVN are just usernames, where in GIT they are in format

John Smith <john.smith@mail.something>

So at the end we should produce a mapping file that looks like:

jsmith = John Smith <john.smith@mail.something>
ltorvalds = Linus <linus@linux.org>

So execute the following command in your checkout svn repository, in order to create a file with the mapping svn-git-users-mapping.txt

svn log -q | awk -F '|' '/^r/ {sub("^ ", "", $2); sub(" $", "", $2); print $2" = "$2" <"$2">"}' | sort -u > svn-git-users-mapping.txt

Edit the produced file with correct User names and emails on the right side.

Cloning SVN repository into GIT repository

The following code executed in terminal will first create a directory, and clone svn into git repository in this directory, using svn-git-users-mapping.txt file for transforming users.

mkdir YOUR_GIT_REPO_DIR 
git svn clone YOUR_SVN_REPOSITORY_URL -A svn-git-users-mapping.txt --stdlayout YOUR_GIT_REPO_DIR

This script uses the standard SVN layout (trunk, branches, tags) - if you have a different structure - you can explicitly specify it, using parameters (-T trunk -b branches -t tags)

Migrating branches

Now is time to migrate branches - enter the created directory (YOUR_GIT_REPO_DIR) and execute the following script (this is a bash script, so if you use another shell, maybe you have to adjust it):

for branch in `git branch -r | grep -v -e 'tags\/\(.*\)' | sed 's/  \(.*\)/\1/g'`
do
        remote_branch="remotes/$branch"
        echo "About to checkout branch $remote_branch into $branch"
        echo "============================================="
        git checkout -b "$branch" "$remote_branch"
done

Similar process is used for the next point too:

Migrating tags

for branch in `git branch -r | grep -e '\(tags\/\)\(.*\)' | sed 's/\(tags\/\)\(.*\)/\2/g'`
do
    remote_branch="remotes/tags/$branch"
    new_tag="tag_$branch"
    echo "About to checkout tag $remote_branch into $new_tag"
    echo "============================================="
    git checkout -b "$new_tag" "$remote_branch"
    git checkout master
    git tag $branch "$new_tag"
    git branch -D "$new_tag"
done

Now that we have fully migrated repository, if we want a detached one from SVN (currently the created repo is connected to svn and can be used that way, with commends git svn rebase --all - to fetch and rebase all changes from SVN, and git svn dcommit --interactive - to push changes from git local commits to remote SVN repo).

Next step:

Creating new GIT detached repository and pushing all changes to it

git init --bare NEW_GIT_REPO
cd NEW_GIT_REPO
git symbolic-ref HEAD refs/heads/trunk

cd YOUR_GIT_REPO_DIR
git remote add NEW_GIT_REPO ../NEW_GIT_REPO
git config remote.NEW_GIT_REPO.push 'refs/remotes/*:refs/heads/*'
git push NEW_GIT_REPO

Now you are ready to use the newly created GIT repository, having all your history, branches and tags.

In next article I will try to share my experience of using SVN as central repository, and GIT as local versioning and client.

Here are some links that I used, while researching the best way to do the migration:

Converting a Subversion repository to Git

Stackoverflow: How to migrate SVN with history to a new Git repository?

Experimenting with Git at Slide (Part 13)

Tool to manage svn-externals with git

~Enjoy