I have been maintaining my own SVN server for many years, but in order to share code and make use of managed services, it was time to migrate some of my repositories to Git.
There are many tutorials for svn-git migration, here’s a customised script which works for me: migrate-svn-to-git.sh. Note, it requires an authors.txt file – there any plenty of adequate resources out there for how to create one.
There is nothing specific about this script for Google Source Repos, that is just my choice for private code so it can make use of Google Cloud Build and gcr.io.
#!/usr/bin/env bash
svnUri="$1"
gitUri="$2"
if [[ -z "${svnUri}" || -z "${gitUri}" ]]; then
echo "[ERROR] Usage migrate-svn-to-git.sh <svn_uri> <git_uri>" 1>&2
exit 1
fi
if [[ ! -f authors.txt ]]; then
echo "[ERROR] authors.txt is missing" 1>&2
exit 1
fi
echo "[INFO] Cloning from SVN: ${svnUri}"
git svn --authors-file=authors.txt clone -s ${svnUri} --prefix svn/ migration
cd migration
echo "[INFO] Creating Git tags"
for t in $(git for-each-ref --format='%(refname:short)' refs/remotes/svn/tags); do git tag $(echo ${t} | sed 's^svn/tags/^^') ${t} && git branch -D -r ${t}; done
echo "[INFO] Creating Git branches"
for b in $(git for-each-ref --format='%(refname:short)' refs/remotes/svn | grep -v trunk); do git branch $(echo ${b} | sed 's^svn/^^') refs/remotes/${b} && git branch -D -r ${b}; done
echo "[INFO] Creating .gitignore file"
git svn show-ignore > .gitignore
git add .gitignore
git commit -m "Added .gitignore"
echo "[INFO] Pushing to Git: ${gitUri}"
git remote add google ${gitUri}
git push --force google --tags
git push --force google --all
cd -
echo "[INFO] Removing migration directory"
rm -rf migration
Once you have created the Git repo, you need to switch your working copy of a project from SVN to Git. Here’s a script: switch-svn-to-git.sh
#!/usr/bin/env bash
gitUri="$1"
if [[ -z "${gitUri}" ]]; then
echo "[ERROR] Usage switch-svn-to-git.sh <git_uri>" 1>&2
exit 1
fi
if [[ ! -d .svn ]]; then
echo "[ERROR] Not a SVN project" 1>&2
exit 1
fi
echo "[INFO] Finding current branch"
svnBranch=$(svn info | grep '^URL:' | egrep -o '(tags|branches)/[^/]+|trunk' | egrep -o '[^/]+$')
echo "[DEBUG] ${svnBranch}"
echo "[INFO] Cleaning SVN directory"
rm -rf .svn
echo "[INFO] Initialising Git from: ${gitUri}"
git init
git remote add origin ${gitUri}
git fetch
echo "[INFO] Saving working copy"
git show origin/master:.gitignore > .gitignore
git checkout -b tmp
git add .
git commit -m "local changes"
echo "[INFO] Checking out branch"
gitBranch="master"
if [[ ${svnBranch} != "trunk" ]]; then
gitBranch="${svnBranch}"
fi
git checkout ${gitBranch}
echo "[INFO] Merging working copy"
git merge --allow-unrelated-histories -X theirs --squash tmp
git branch --delete --force tmp
echo "[INFO] Deleting IntelliJ reference to SVN (if exists)"
test -f .idea/vcs.xml && rm .idea/vcs.xml
echo "[INFO] Done - you may want to set your name / email with: git config user.email <email>"