Converting a Subversion SVN Repository to Git


I’ve used DreamHost’s SVN hosting with past projects I’ve done. It wasn’t till recently that I had time to migrate them over to Git. Searching the net, I found JohnAlbin’s steps on how to do so efficiently (written in August 2010). ((If you have Ruby, you may try svn2git tool, which will skip steps 1-6.))

Here’s a slightly-updated-shorter version of that (containing steps of my migration to Bitbucket): ((Unlimited private and public repos?! Why not. Get yours at https://bitbucket.org/))

  1. Retrieve a list of all Subversion committers

    From the root of your local Subversion checkout, 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
    into something like this:
    stechico = Sherwin Techico

  2. Clone the Subversion repository 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 “standard layout”, but was using design/docs/www. So I had to update the file structure before doing this step. I ended up moving design and docs into branches, and renaming www to trunk.

    After running the “git svn clone,” there were apparently some branches that didn’t need to be there. I just then deleted those by using the following, 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. Convert svn:ignore properties to .gitignore (per case basis)
    cd ~/temp
    git svn show-ignore > .gitignore
    git add .gitignore
    git commit -m 'Convert svn:ignore properties to .gitignore.'
  4. Push repository to a bare git repository

    First, create a bare repository 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 repository 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 repository can now be safely deleted.

  5. Rename “trunk” branch to “master

    The main dev branch “trunk” (default in Subversion) needs to be renamed to Git’s standard “master” branch:

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

    git-svn makes all of Subversions tags into very-short branches in Git of the form “tags/name”. We’ll want to convert all those branches into actual Git tags using: ((This multi-line code will be properly formatted once copy-and-pasted onto a unix shell.))

    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 created a new Bitbucket (Git) repo. Then, imported the existing repo by adding a remote:

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

    The latter command above will push all branches. If you just want to push master, use:

    git push -u origin master

Note:
If you are wanting to also create a new branch without any ancestry, execute the following commands 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: JohnAlbin & Git Community Boook