Converting a Subversion SVN Repository to Git

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

Here’s a slight­ly-updat­ed-short­er ver­sion of that (con­tain­ing steps of my migra­tion to Bit­buck­et):2

  1. Retrieve a list of all Sub­ver­sion com­mit­ters

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

    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­to­ry using git-svn
    git svn clone [SVN repo URL] --no-metadata -A authors-transform.txt --stdlayout ~/temp

    In some of my ear­ly projects, I was­n’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 end­ed up mov­ing design and docs into branch­es, and renam­ing www to trunk.

    After run­ning the “git svn clone,” there were appar­ent­ly some branch­es that did­n’t need to be there. I just then delet­ed those by using the fol­low­ing, for exam­ple:

    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­to­ry to a bare git repos­i­to­ry

    First, cre­ate a bare repos­i­to­ry 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­to­ry to the new bare repos­i­to­ry.

    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­to­ry can now be safe­ly delet­ed.

  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 branch­es and tags

    git-svn makes all of Sub­ver­sions tags into very-short branch­es in Git of the form “tags/name”. We’ll want to con­vert all those branch­es into actu­al 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­at­ed a new Bit­buck­et (Git) repo. Then, import­ed 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 branch­es. If you just want to push mas­ter, use:

    git push -u origin master

Note:
If you are want­i­ng 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­ni­ty Boook

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

2 Comments

Comments Feed
  1. Venkat

    I did most of this. But my new git repo does­n’t list branch­es when I run git branch ‑a I get

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

    when I know there are oth­er branch­es. Are your branch­es con­vert­ed prop­er­ly ?

    • Sherwin

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