- Generate Git authors file
- Create Git repository
- Handling irregular branch structures
- Create local branches from remotes/svn/*
- Create clean Git remote and populate
- Other useful links
$ svn log -q file://path/to/svn/root | \
awk -F '|' '/^r/ {sub("^ ", "", $2); sub(" $", "", $2); print $2" = "$2" <"$2">"}' | \
sort -u > gitauthors.txt
$ echo "(no author) = Unknown User <unknown.user@emailaddr>" >> gitauthors.txt
Tweak the generated gitauthors.txt
to suit, adding in fullname and email address details. Including a final line of (no author) = Unknown User <unknown.user@emailaddr>
allows for a "catch all" user.
# init new Git repo based off source SVN repo
# note: may need to tweak --trunk/--tags/--branches/--stdlayout to suit, refer to man git-svn(1)
$ git svn clone \
--authors-file=gitauthors.txt \
--trunk=svn/path/to/trunk \
--no-metadata --prefix=svn/ \
svn+ssh://user@svnserver/path/to/svn/repository gitrepo.tmp
# fetch repo contents from SVN
$ git svn fetch
# now branch remotes/svn/trunk as the new local master
$ cd gitrepo.tmp
$ git branch -m master master.old
$ git checkout -b master svn/trunk
$ git branch -D master.old
In the instance where source branches aren't all contained nicely within a within a single sub-tree (e.g. /branches/*/
), or you wish to cherry-pick specific branches to export to the new Git repository. In this case we can't simply git svn clone
, but need to use a little git config
trickery to get the job done.
# init new Git repo based off source SVN repo
$ git svn init \
--authors-file=gitauthors.txt \
--trunk=svn/path/to/trunk \
--no-metadata --prefix=svn/ \
svn+ssh://user@svnserver/path/to/svn/repository gitrepo.tmp
# add two branch pattern matching examples, will ONLY match/import the following branches
# - /branches/one/
# - /branches/two/
# - /branches/three/
# - /branches/four/
# - /branches/subtopic/apples/
# - /branches/subtopic/oranges/
$ git config --local --add svn-remote.svn.branches \
"branches/{one,two,three,four}:refs/remotes/svn/*"
$ git config --local --add svn-remote.svn.branches \
"branches/subtopic/{apples,oranges}:refs/remotes/svn/*"
# fetch repo contents from SVN
$ git svn fetch
# now branch remotes/svn/trunk as the new local master
$ cd gitrepo.tmp
$ git branch -m master master.old
$ git checkout -b master svn/trunk
$ git branch -D master.old
Script would be run from the freshly created Git repository directory gitrepo.tmp
outlined in previous step.
#!/bin/bash -e
# convert all remaining remotes/svn branches into local branches
for branchName in `git branch -r | \
grep '^ *svn/' | grep -v '^ *svn/tags/' | grep -v '^ *svn/trunk$' | \
grep -vE '^ *svn/.+@[0-9]+$'`; do
echo $branchName
git checkout -b `echo $branchName | sed -e 's/^svn\///'` $branchName
done
Taking the corrected repository in gitrepo.tmp
and pushing all branches to a new Git shared remote in gitrepo.remote
for a development team to start using.
#!/bin/bash -e
GIT_REPO_TMP_DIR="gitrepo.tmp"
GIT_REPO_REMOTE_DIR="gitrepo.remote"
# create a new Git remote and push all local branches from our cleaned temp repository into it
git init --bare --shared=group $GIT_REPO_REMOTE_DIR
git --git-dir=$GIT_REPO_TMP_DIR/.git remote add origin $GIT_REPO_REMOTE_DIR
for branchName in `git --git-dir=$GIT_REPO_TMP_DIR/.git branch | sed -e 's/^* //'`; do
echo $branchName
git --git-dir=$GIT_REPO_TMP_DIR/.git push origin $branchName
done
Also you can push your SVN remotes created in gitrepo.tmp
directly into a Git shared remote gitrepo.remote
, (with target branch renaming too if needed) - like so.
#!/bin/bash -e
GIT_REPO_TMP_DIR="gitrepo.tmp"
GIT_REPO_REMOTE_DIR="gitrepo.remote"
git init --bare --shared=group $GIT_REPO_REMOTE_DIR
git --git-dir=$GIT_REPO_TMP_DIR/.git remote add transfer $GIT_REPO_REMOTE_DIR
for branchName in `git --git-dir=$GIT_REPO_TMP_DIR/.git branch -r | \
grep '^ *svn/' | grep -vE '^ *svn/.+@[0-9]+$'`; do
echo $branchName
git --git-dir=$GIT_REPO_TMP_DIR/.git push transfer \
$branchName:refs/heads/`echo $branchName | sed -e 's/^svn\///'`
done
# or to rename a source branch in the targer
git --git-dir=$GIT_REPO_TMP_DIR/.git push transfer svn/somebranchname:refs/heads/targetbranchname