Logo
Color-Of-Code
  Home   All tags   Terms and Conditions

Svn to Git

November 23, 2023

SVN to GIT migration

Steps to migrate a svn repository into a git repository

Environment variables

In order to ease the reuse of these explanations let't define some variables:

SVN_URL can be some path within a repository, there is no need to specify a whole SVN repository, only parts of it can be migrated.

Build authors-transform configuration

The authors-transform.txt file is needed to map svn users onto corresponding git users.

Export log comments

svn log -q $SVN_URL > commit-log.txt
cat commit-log.txt | awk -F '|' '/^r/ {sub("^ ", "", $2); sub(" $", "", $2); 
print $2" = "$2" <"$2">"}' | sort -u > authors-transform.txt

You now should edit the resulting authors-transform.txt according to your infrastructure and wanted user mappings.

Clone the svn repository

Clone the svn repository with --no-metadata to avoid addition of info like git-svn-id to the log comment. But do not use --no-metadata if you intend to still use your svn repository

git svn clone $SVN_URL --no-metadata -A authors-transform.txt --stdlayout $GIT_SVN

Or if the layout is non standard (-t, -b option can be set multiple times), this is broken in git-2.5.1:

git svn clone $SVN_URL --no-metadata -A authors-transform.txt \
	-T Trunk -b Branches -t Tags --prefix svn/ $GIT_SVN

You can stop and proceed by using the same command.

Git ignore file

Convert svn:ignore properties to `.gitignore``

pushd $GIT_SVN
git svn show-ignore --id=$PREFIX/trunk > .gitignore
git add .gitignore
git commit -m 'Convert svn:ignore properties to .gitignore.'
popd

Checks

Check other unhandled properties if you need to check for exernals for example

There is one file per branch/tag:

cat .git/svn/refs/remotes/*/trunk/unhandled.log

cat .git/svn/refs/remotes/*/trunk/unhandled.log | grep _prop | grep -v "svn:ignore"

Other branches

List origin branches (assuming origin is your prefix)

for branch in `git branch -r | grep "$PREFIX/" | sed "s/ $PREFIX\///"`; do
  echo "branch defined in $PREFIX: $branch"
done

Convert origin branches to local branches (assuming origin is your prefix)

for branch in `git branch -r | grep "$PREFIX/" | sed "s/ $PREFIX\///"`; do
  git branch $branch refs/remotes/$PREFIX/$branch
done

Clean up branches and tags

git-svn makes all of Subversions tags into very-short branches in Git of the form tags/name. You'll want to convert all those branches into actual Git tags using:

git for-each-ref --format='%(refname)' refs/heads/tags |
 cut -d / -f 4 |
 while read ref
 do
   git tag "$ref" "refs/heads/tags/$ref";
   git branch -D "tags/$ref";
 done

Clean history

Remove empty commits by rewriting the history

git filter-repo --strip-blobs-bigger-than 0M

Rename trunk branch to main

git branch -m trunk main

References

Interesting additional links