Converting a Subversion SVN Repository to Git

I’ve used DreamHost’s SVN host­ing with past projects I’ve done. It wasn’t till recently that I had time to migrate them over to Git. Search­ing the net, I found JohnAlbin’s steps on how to do so effi­ciently (writ­ten in August 2010).1

Here’s a slightly-updated-shorter ver­sion of that (con­tain­ing steps of my migra­tion to Bit­bucket):2

  1. Retrieve a list of all Sub­ver­sion committers

    From the root of your local Sub­ver­sion check­out, run this command:

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

    Edit each line in authors-transform.txt:
    stechico = stechico <stechico>
    into some­thing like this:
    stechico = Sherwin Techico <stechico@example.com>

  2. Clone the Sub­ver­sion repos­i­tory using git-svn
    git svn clone [SVN repo URL] --no-metadata -A authors-transform.txt --stdlayout ~/temp

    In some of my early projects, I wasn’t using the “stan­dard lay­out”, but was using design/docs/www. So I had to update the file struc­ture before doing this step. I ended up mov­ing design and docs into branches, and renam­ing www to trunk.

    After run­ning the “git svn clone,” there were appar­ently some branches that didn’t need to be there. I just then deleted those by using the fol­low­ing, for example:

    git branch -rd design@364
    git branch -rd docs@364
    git branch -rd tags/template-structure@364
    git branch -rd trunk@364
    git branch -rd v4@364
    git branch -rd v5@364
  3. Con­vert svn:ignore prop­er­ties to .git­ig­nore (per case basis)
    cd ~/temp
    git svn show-ignore > .gitignore
    git add .gitignore
    git commit -m 'Convert svn:ignore properties to .gitignore.'
  4. Push repos­i­tory to a bare git repository

    First, cre­ate a bare repos­i­tory and make its default branch match svn’s “trunk” branch name.

    git init --bare ~/new-bare.git
    cd ~/new-bare.git
    git symbolic-ref HEAD refs/heads/trunk

    Push the ~/temp repos­i­tory to the new bare repository.

    cd ~/temp
    git remote add bare ~/new-bare.git
    git config remote.bare.push 'refs/remotes/*:refs/heads/*'
    git push bare

    The ~/temp repos­i­tory can now be safely deleted.

  5. Rename “trunk” branch to “mas­ter

    The main dev branch “trunk” (default in Sub­ver­sion) needs to be renamed to Git’s stan­dard “mas­ter” branch:

    cd ~/new-bare.git
    git branch -m trunk master
  6. Clean up branches and tags

    git-svn makes all of Sub­ver­sions tags into very-short branches in Git of the form “tags/name”. We’ll want to con­vert all those branches into actual Git tags using:3

    cd ~/new-bare.git
    git for-each-ref --format='%(refname)' refs/heads/tags |
    cut -d / -f 4 |
    while read ref
    do
      git tag "$ref" "refs/heads/tags/$ref";
      git branch -D "tags/$ref";
    done
  7. Share your new Git repo

    For this step, I cre­ated a new Bit­bucket (Git) repo. Then, imported the exist­ing repo by adding a remote:

    git remote add origin ssh://git@bitbucket.org/username/new-git-repository.git
    git push -u --all origin

    The lat­ter com­mand above will push all branches. If you just want to push mas­ter, use:

    git push -u origin master

Note:
If you are want­ing to also cre­ate a new branch with­out any ances­try, exe­cute the fol­low­ing com­mands from any branch:

git symbolic-ref HEAD refs/heads/your-new-branch
rm .git/index 
git clean -fdx

//Add your files to your new branch, then execute the following
git add -all
git commit -m 'Initial commit'

There you have it… I hope this helps you migrate your code/projects.

Source: JohnAl­bin & Git Com­mu­nity Boook

  1. If you have Ruby, you may try svn2git tool, which will skip steps 1–6. []
  2. Unlim­ited pri­vate and pub­lic repos?! Why not. Get yours at https://bitbucket.org/ []
  3. This multi-line code will be prop­erly for­mat­ted once copy-and-pasted onto a unix shell. []

2 Comments

Comments Feed · Trackback Address
  1. Venkat

    I did most of this. But my new git repo doesn’t list branches when I run git branch –a I get

    * mas­ter
    remotes/origin/HEAD -> origin/master
    remotes/origin/master

    when I know there are other branches. Are your branches con­verted properly ?

    • Sherwin

      Par­don the late reply @Venkat, for what I did, yes… mine were con­verted prop­erly. Let’s hope some­one can update and help you out.

Leave a Comment

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>