How do I migrate an SVN repository with history to a new Git repository?
Solution 1
Magic:
$ git svn clone http://svn/repo/here/trunk
Git and SVN operate very differently. You need to learn Git, and if you want to track changes from SVN upstream, you need to learn git-svn
. The git-svn
main page has a good examples section:
$ git svn --help
Solution 2
Create a users file (i.e. users.txt
) for mapping SVN users to Git:
user1 = First Last Name <[email protected]>
user2 = First Last Name <[email protected]>
...
You can use this one-liner to build a template from your existing SVN repository:
svn log -q | awk -F '|' '/^r/ {gsub(/ /, "", $2); sub(" $", "", $2); print $2" = "$2" <"$2">"}' | sort -u > users.txt
SVN will stop if it finds a missing SVN user, not in the file. But after that, you can update the file and pick up where you left off.
Now pull the SVN data from the repository:
git svn clone --stdlayout --no-metadata --authors-file=users.txt svn://hostname/path dest_dir-tmp
This command will create a new Git repository in dest_dir-tmp
and start pulling the SVN repository. Note that the "--stdlayout" flag implies you have the common "trunk/, branches/, tags/" SVN layout. If your layout differs, become familiar with --tags
, --branches
, --trunk
options (in general git svn help
).
All common protocols are allowed: svn://
, http://
, https://
. The URL should target the base repository, something like http://svn.mycompany.com/myrepo/repository. The URL string must not include /trunk
, /tag
or /branches
.
Note that after executing this command it very often looks like the operation is "hanging/frozen", and it's quite normal that it can be stuck for a long time after initializing the new repository. Eventually, you will then see log messages which indicate that it's migrating.
Also note that if you omit the --no-metadata
flag, Git will append information about the corresponding SVN revision to the commit message (i.e. git-svn-id: svn://svn.mycompany.com/myrepo/<branchname/trunk>@<RevisionNumber> <Repository UUID>
)
If a user name is not found, update your users.txt
file then:
cd dest_dir-tmp
git svn fetch
You might have to repeat that last command several times, if you have a large project until all of the Subversion commits have been fetched:
git svn fetch
When completed, Git will checkout the SVN trunk
into a new branch. Any other branches are set up as remotes. You can view the other SVN branches with:
git branch -r
If you want to keep other remote branches in your repository, you want to create a local branch for each one manually. (Skip trunk/master.) If you don't do this, the branches won't get cloned in the final step.
git checkout -b local_branch remote_branch
# It's OK if local_branch and remote_branch are the same names
Tags are imported as branches. You have to create a local branch, make a tag and delete the branch to have them as tags in Git. To do it with tag "v1":
git checkout -b tag_v1 remotes/tags/v1
git checkout master
git tag v1 tag_v1
git branch -D tag_v1
Clone your GIT-SVN repository into a clean Git repository:
git clone dest_dir-tmp dest_dir
rm -rf dest_dir-tmp
cd dest_dir
The local branches that you created earlier from remote branches will only have been copied as remote branches into the newly cloned repository. (Skip trunk/master.) For each branch you want to keep:
git checkout -b local_branch origin/remote_branch
Finally, remove the remote from your clean Git repository that points to the now-deleted temporary repository:
git remote rm origin
Solution 3
Cleanly Migrate Your Subversion Repository To a Git Repository. First you have to create a file that maps your Subversion commit author names to Git commiters, say ~/authors.txt
:
jmaddox = Jon Maddox <[email protected]>
bigpappa = Brian Biggs <[email protected]>
Then you can download the Subversion data into a Git repository:
mkdir repo && cd repo
git svn init http://subversion/repo --no-metadata
git config svn.authorsfile ~/authors.txt
git svn fetch
If you’re on a Mac, you can get git-svn
from MacPorts by installing git-core +svn
.
If your subversion repository is on the same machine as your desired git repository, then you can use this syntax for the init step, otherwise all the same:
git svn init file:///home/user/repoName --no-metadata
Solution 4
I used the svn2git script and works like a charm.
Solution 5
I suggest getting comfortable with Git before trying to use git-svn constantly, i.e. keeping SVN as the centralized repo and using Git locally.
However, for a simple migration with all the history, here are the few simple steps:
Initialize the local repo:
mkdir project
cd project
git svn init http://svn.url
Mark how far back you want to start importing revisions:
git svn fetch -r42
(or just "git svn fetch" for all revs)
Actually, fetch everything since then:
git svn rebase
You can check the result of the import with Gitk. I'm not sure if this works on Windows, it works on OSX and Linux:
gitk
When you've got your SVN repo cloned locally, you may want to push it to a centralized Git repo for easier collaboration.
First create your empty remote repo (maybe on GitHub?):
git remote add origin [email protected]:user/project-name.git
Then, optionally sync your main branch so the pull operation will automatically merge the remote master with your local master when both contain new stuff:
git config branch.master.remote origin
git config branch.master.merge refs/heads/master
After that, you may be interested in trying out my very own git_remote_branch
tool, which helps to deal with remote branches:
First explanatory post: "Git remote branches"
Follow-up for the most recent version: "Time to git collaborating with git_remote_branch"
Milan Babuškov
Software developer, owner of a small ISV company, project manager of the open source FlameRobin project. Specialized in Linux, C++, PHP and Relational databases. You can read my software related blog at http://www.BackwardCompatible.net You can also buy my shareware software at http://www.GuacoSoft.com
Updated on August 03, 2022Comments
-
Milan Babuškov over 1 year
I read the Git manual, FAQ, Git - SVN crash course, etc. and they all explain this and that, but nowhere can you find a simple instruction like:
SVN repository in:
svn://myserver/path/to/svn/repos
Git repository in:
git://myserver/path/to/git/repos
git-do-the-magic-svn-import-with-history \ svn://myserver/path/to/svn/repos \ git://myserver/path/to/git/repos
I don't expect it to be that simple, and I don't expect it to be a single command. But I do expect it not to try to explain anything - just to say what steps to take given this example.