Friday, November 18, 2011

Migrating from SVN to Git


Interested in migrating an existing Subversion (SVN) based open source project to git?


Here's are my migration steps I went through for my open source projects, which are up on Google Code Project hosting:




1. Get a complete list of SVN committers
for prj in gwt-log gwt-dnd gwt-voices
do
  svn log -q https://$prj.googlecode.com/svn | \
  awk -F '|' '/^r/ {sub("^ ", "", $2); sub(" $", "", $2); print $2" = "$2" <"$2">"}' | \
  sort -u >>~/authors.txt
done




2. Update the ~/authors.txt mapping file
vi ~/authors.txt

The svn username is on the left. The new git username and email are on the right. After modifications, mine looked like this:
(no author) = (no author) <(no author)>
fredsa = Fred Sauer <fredsa@gmail.com>
fredsa@gmail.com = Fred Sauer <fredsa@gmail.com>
fredsa@google.com = Fred Sauer <fredsa@google.com>




3. Convert your SVN commit history into a local git repository
# wiki
cd
for prj in gwt-log gwt-dnd gwt-voices
do
  git svn clone https://$prj.googlecode.com/svn/wiki --no-minimize-url -A ~/authors.txt $prj.wiki
done


# project source
cd
for prj in gwt-log gwt-dnd gwt-voices
do
  git svn clone https://$prj.googlecode.com/svn \
    --stdlayout \
    --ignore-paths=^wiki \
    -A ~/authors.txt \
    $prj
  cd ~/$prj


  git svn show-ignore > .gitignore
  git add .gitignore
  git commit -m 'Convert svn:ignore properties to .gitignore.'


  # replace refs/remotes/tags/... branches with annotated tags
  #
  git for-each-ref \
    --format='%(refname)' \
    refs/remotes/tags/ | \
    cut -d / -f 4 | \
    while read ref
    do
      git tag -a \
        -m "git-svn conversion" \
        "$ref" "refs/remotes/tags/$ref";
      git branch -D -r "tags/$ref";
    done


  # mirror remote svn branches with local branches,
  # so we can push those up to the new git repository
  #
  git for-each-ref \
    --format='%(refname)' \
    refs/remotes/ |
    cut -d / -f 3 | \
    while read ref
    do
      git branch  "$ref" "refs/remotes/$ref";
    done


  # drop svn trunk branch as we're divorcing ourselves from svn
  git branch -d trunk
done




4. Validate the local git repository
git branch -va
git tag -l
gitk -a
...


5. Flip the switch
Go to http://code.google.com/p/$prj/adminSource and switch each project from svn to git. The SVN repositories have now been hidden and your project has new, empty git repositories.


6. Push your git changes
Push your new git commit history into the empty git repositories.
# wiki
for prj in gwt-log gwt-dnd gwt-voices
do
  cd ~/$prj.wiki
  git push --all https://code.google.com/p/$prj.wiki/
done


# project source
cd
for prj in gwt-log gwt-dnd gwt-voices
do
  cd ~/$prj
  # push commit history and branches
  git push --all https://code.google.com/p/$prj/


  # push our local tags as well
  git push --tags https://code.google.com/p/$prj/
done




That's it. You're done.

No comments: