Showing posts with label moving to git. Show all posts
Showing posts with label moving to git. Show all posts

How to: migrate SVN repository to Git and keep history

Hi all,

Today we are going to cover topic about moving from Subversion to Git and ways to copy / migrate SVN data to Git repository (so we can keep the history of commits)

I would recommend doing the migration process using Linux OS as it seems to be much faster than on Windows OS (at least when I was testing it) - this is especially for large repositories.


  • Create "authors" file that relates to SVN repo commit authors. It should be in the following format:
username1 = user_firstname user_lasname <user_email>


username2 = user_firstname user_lasname <user_email>
and so on...



  • Tell Git about it: 
git config --global svn.authorsfile <path_to_authors_file>

  • Init Git repository with SVN reference:
git svn init <svn_repo_url> --stdlayout --prefix=svn/

  • Review/edit .git/config file, it should look like this:
[svn-remote "svn"]
url = <svn_repo_url>
fetch = trunk:refs/remotes/svn/trunk
branches = branches/*:refs/remotes/svn/*
tags = tags/*:refs/remotes/svn/tags/*
[svn]
authorsfile = /path/to/authors.txt

If the SVN repository is large you might want to limit the fetch to only some branches and tags. If so you can do it by specifying them in the .git/config file, for example:
[svn-remote "svn"]
url = <svn_repo_url>
fetch = trunk:refs/remotes/svn/trunk
branches = branches/{feature_branchA,old_branchB,branch_test}:refs/remotes/svn/*
        tags = tags/{tagA,tagB,tagC}:refs/remotes/svn/tags/*


  • Fetch the commits: git svn fetch
Occasionally it may stop due to some random errors or due to unknown commit author. In that case you can add new row/entry in your authors. You can also try to clear memory by running:
git gc OR/AND git svn gc

To resume and continue the fetch run: git svn fetch

  • After a while depending on the repository size it will finish and you can view all available SVN branches by running the command: git branch -a

  • Next step is to create Git branches and tags to the corresponding SVN branches and tags. For each SVN branch run the following command:
git checkout -b <BRANCH_NAME> svn/<BRANCH_NAME>

  • The similar thing for tags, but you might choose to leave tags as branches whatever you prefer:
git checkout -b <tag_TAGNAME> svn/tags/<TAG_NAME> // creates a branch for SVN tag
git checkout master
git tag <TAGNAME> <tag_TAGNAME> // create git tag to that branch
git branch -D <tag_TAGNAME> // delete the previously created branch, tags stays

Repeat for each SVN tag.
  • Switch to the master and create .gitignore file:
git svn show-ignore > .gitignore
// edit .gitignore to manually add whatever you want to ignore
git add .gitignore
git commit -m 'Convert svn:ignore properties to .gitignore.'

Alternatively and/or additionally you can set ignore globally for that repo:
git svn show-ignore >> .git/info/exclude 
  • define remote Git repository so it's added to the .git/config
git remote add origin <GIT_REPO_URL>
  • push everything to the Git repository
git push -u origin -all // push all branches and changes to the repo named origin
git push --tags origin // push the tags as previous command ignores tags

Additions/updates

A) If you want to add some branch or tag later you can do it by telling about it in .git/config:
[svn-remote "branch_MyBranchX"]
url = <SVN_REPO_URL>branches/MyBranchX/

    fetch = :refs/remotes/svn/MyBranchX

Then:

  • Fetch it: git svn fetch
  • Create git branch for it: git svn checkout -b MyBranchX svn/MyBranchX
  • Push it: git push origin MyBranchX

B) If you want to update existing branch from SVN because your team has not switched SVN off yet and you want to sync later changes just fetch the changes:

git svn fetch OR git svn fetch <BRANCH_NAME>

Then switch to related Git branches and rebase:
git checkout <EXISTING_GIT_BRANCH_NAME>
git rebase svn/<BRANCH_NAME> // sync with the recent changes from SVN
git push origin <BRANCH_NAME>

This is it! Happy migrationg :)