Skip to content

Instantly share code, notes, and snippets.

@zhenyanghua
Last active March 16, 2016 15:34
Show Gist options
  • Save zhenyanghua/bc40567e6c0d0edde3ff to your computer and use it in GitHub Desktop.
Save zhenyanghua/bc40567e6c0d0edde3ff to your computer and use it in GitHub Desktop.
Migration from SVN to GIT

Migration from SVN to Git

Migration is not always easy. However, git-svn is a quite useful tool to do the job.

To do the job right, this post from stackoverflow is tremendously helpful in my entire process.

I wrote the m.py to automate the entire process.

#!/usr/bin/env python
"""
m.py: Migrate svn to git.
Beware that this version ignore the initial direction creation commit.
"""
__author__ = "Zhenyang Hua"
__license__ = "MIT"
__version__ = "0.0.1"
__maintainer__ = "Zhenyang Hua"
__email__ = "edison.hua@gmail.com"
__status__ = "Development"
from subprocess import (PIPE, Popen)
import os
import shutil
"""
Settings
"""
# Don't miss the trailing slash
svnUsername = "svn username"
svnRemoteRepo = "url to svn remote repo"
gitRemoteRepo = "url to git remote repo"
"""
Program starts here
"""
root = os.path.dirname(os.path.abspath(__file__))
svnUrlParts = svnRemoteRepo.split('/')
svnLocalRepo = "./" + svnUrlParts[len(svnUrlParts) - 2]
gitUrlParts = gitRemoteRepo.split('/')
gitLocalRepo = "./" + gitUrlParts[len(gitUrlParts) - 2]
starting_revision = ""
def invoke(command):
return Popen(command, stdout=PIPE, shell=True).stdout.read()
def getSvnRepo():
co = "svn co " + svnRemoteRepo
invoke(co)
def getAuthors():
os.chdir(svnLocalRepo)
lines = invoke("svn log -q").split('\n')
authorList = []
revisionList = []
for line in lines:
entry = line.split(' | ')
if (len(entry) > 1):
name = entry[1]
author = name + " = " + name + ' <' + name + '@woolpert.com>'
authorList.append(author)
revision = entry[0]
revisionList.append(revision)
authorList = sorted(list(set(authorList)));
with open("../author_list.txt", "w") as authorListTxt:
for author in authorList:
authorListTxt.write(author)
global starting_revision
starting_revision = revisionList[len(revisionList) - 2][1:]
def checkAuthors():
editingWarning = "> Please make sure you have updated the author_list.txt, enter Y to confirm: "
response = raw_input(editingWarning)
if response.upper() == "Y":
print "\n> author_list.txt was confirmed.\n"
else:
checkAuthors()
def cloneSvnRepo():
os.chdir(root)
cloneRepo = "git svn clone -r " + starting_revision + " --stdlayout --username=" + svnUsername + " --authors-file=author_list.txt --no-minimize-url " + svnRemoteRepo + " " + gitLocalRepo
invoke(cloneRepo)
os.chdir(gitLocalRepo)
rebase = "git svn rebase"
invoke(rebase)
def pushToGit():
os.chdir(root)
os.chdir(gitLocalRepo)
addRemote = "git remote add origin " + gitRemoteRepo
invoke(addRemote)
pushRepo = "git push origin master"
invoke(pushRepo)
def onerror(func, path, exc_info):
"""
Error handler for ``shutil.rmtree``.
If the error is due to an access error (read only file)
it attempts to add write permission and then retries.
If the error is for another reason it re-raises the error.
Usage : ``shutil.rmtree(path, onerror=onerror)``
"""
import stat
if not os.access(path, os.W_OK):
# Is the error an access error ?
os.chmod(path, stat.S_IWUSR)
func(path)
else:
raise
def cleanup():
os.chdir(root)
if os.path.isdir(svnLocalRepo):
shutil.rmtree(svnLocalRepo, onerror=onerror)
if os.path.isdir(gitLocalRepo):
shutil.rmtree(gitLocalRepo, onerror=onerror)
if os.path.exists("./author_list.txt"):
os.remove("./author_list.txt")
def main():
print "\n----Start----\n"
print "1. Checking out the svn repository...\n"
getSvnRepo()
print "2. Retrieving a list of all Subversion committers...\n"
getAuthors()
print "3. Confirming username and email of the committers\n"
checkAuthors()
print "4. Cloning the Subversion repository using git-svn...\n"
cloneSvnRepo()
print "5. Pushing the local repository to the remote...\n"
pushToGit()
print "6. Cleaning up...\n"
cleanup()
print "----End----\n"
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment