Migrating git to svn (subversion)

I’ve found that most documentation / forum discussion around the web for this topic tends to be about migrating svn to git – so here’s a quick shell script (reconfigure the variables at the start) to help migrate from git to subversion.

This script is also available here: migrate-git-to-svn.sh.txt

#!/bin/bash

# Run this script from an empty working directory - it will:
# 1. git clone from the ORIGIN_GIT URL
# 2. run through a number of stages to construct a local svn repository
# 3. check out the svn repo for you to check
#
# NO error checking is done - you need to look at the output and
# look for any issues. This script DOES delete it's working directories
# on each run (so make sure to start in an empty directory to be safe!)

# Configuration
PROJECT_NAME=MyProjectName
ORIGIN_GIT="git@github.com:UserName/MyProjectName.git"

# Keep track of starting directory to make working in sub-directories easier
BASEDIR=$PWD

# Clone (bare) to main repo from main git repo 
# Base because later stages want to talk only to a bare repo
echo "### Cloning git origin into local bare repo: ${PROJECT_NAME}.git"
if [ -d "${PROJECT_NAME}.git" ] ; then rm -rf "${PROJECT_NAME}.git" ; fi
git clone --bare "${ORIGIN_GIT}"

# Protect the real origin by removing it as a remote in the bare clone
echo "### Protect real origin by removing it as a remote in our clone"
( cd "${PROJECT_NAME}.git"; \
  git remote remove origin; \
  )

# Create an empty svn repository to migrate into
echo "### Create and initialise the target svn repository for the migration: ${PROJECT_NAME}.svnrepo"
if [ -d "${PROJECT_NAME}.svnrepo" ] ; then rm -rf "${PROJECT_NAME}.svnrepo" ; fi
mkdir "${PROJECT_NAME}.svnrepo"
svnadmin create "${PROJECT_NAME}.svnrepo"
svn mkdir --parents "file://${BASEDIR}/${PROJECT_NAME}.svnrepo/${PROJECT_NAME}/"{trunk,branches,tags} -m 'Inititalise empty svn repo'

# git svn (NOTE svn mode - needs the git-svn package installed on debian)
# Clone the new local svn repository into a git repo
# The --stdlayout option tells "git svn" that we are using the "standard" {trunk,branches,tags} directories
echo "### git-svn clone the target svn repo as a git directory (used to import from git and then export to svn): ${PROJECT_NAME}-git2svn"
if [ -d "${PROJECT_NAME}-git2svn" ] ; then rm -rf "${PROJECT_NAME}-git2svn" ; fi
git svn clone "file://${BASEDIR}/${PROJECT_NAME}.svnrepo/${PROJECT_NAME}" --stdlayout "${PROJECT_NAME}-git2svn"

# Set up the bare git clone as the origin for the "${PROJECT_NAME}-git2svn" clone
echo "### Add our git clone as the remote origin for ${PROJECT_NAME}-git2svn"
( cd "${PROJECT_NAME}-git2svn"; \
  git remote add origin "file://${BASEDIR}/${PROJECT_NAME}.git"; \
  )

# Import changes into an import branch in the "${PROJECT_NAME}-git2svn" clone and then export to svn
# Note:
# 1. git fetch first to get branch details
# 2. Then branch to an import branch tracking the remote origin/main
# 3. Rebase that onto master (rebase --root commits all reachable, allows to rebase the root commits)
#    This builds the information needed to sync to svn via dcommit.
# 4. Then use svn dcommit - include author information (to help track who made changes)
echo "### Import full commit history into ${PROJECT_NAME}-git2svn and then send to subversion repo"
( cd "${PROJECT_NAME}-git2svn"; \
  git fetch origin; \
  git checkout -b import origin/main; \
  git rebase --onto master --root; \
  git svn dcommit --add-author-from ; \
  )
  
# Checkout a svn working dir to check the export
echo "### Checking out a working svn directory to check the results: svn-check"
if [ -d svn-check ] ; then rm -rf svn-check ; fi
svn co "file://${BASEDIR}/${PROJECT_NAME}.svnrepo/${PROJECT_NAME}" svn-check
echo "Check the contents/log in svn-check/"

Leave a Reply

Your email address will not be published. Required fields are marked *