Skip to content


Importing a Git tree into a Subversion repository

Recently I worked on some new project, and as always I created a local Git repository as a start. After working on it several days, creating lots of commits, I had to publish it into the central Subversion repository (which is one of the VCSs we got). I could have done this by creating a new folder in SVN and add the latest version of all files of the project to it, but that way all history would be gone, which I didn’t like.

Git has a feature to work with SVN repositories, git-svn, but that’s intended to check out existing code from SVN and work on it, not publishing an existing Git tree into a Subversion repository.

A first rather naive approach didn’t work out (as somewhat expected), but then I figured out how to achieve this anyway.

As a test, let’s first create an empty SVN repository and a Git repository with some commits:

$ svnadmin create repo
$ svn co file:///Users/nicolas/Temp/git_to_svn/repo svn_repo
Checked out revision 0.
$ cd svn_repo
$ svn mkdir trunk tags branches
A         trunk
A         tags
A         branches
$ svn commit -m "Create repository structure"
Adding         branches
Adding         tags
Adding         trunk

Committed revision 1.
$ cd ..

$ mkdir project; cd project
$ git init
Initialized empty Git repository in /Users/nicolas/Temp/git_to_svn/project/.git/
$ echo "foo" > test.txt; git add test.txt; git commit -m "Initial version"
master (root-commit) 88464cf] Initial version
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 test.txt
$ echo "bar" > test.txt; git commit test.txt -m "Second version"
master cb62866] Second version
 1 files changed, 1 insertions(+), 1 deletions(-)

We now can set up git-svn:

$ git svn init -s file:///Users/nicolas/Temp/git_to_svn/repo/
$ git svn fetch
r1 = 741ab63aea786882eafd38dc74369e651f554c9c (trunk)

Depending on the layout of your SVN project, you might need to drop the -s parameter and add -t, -T or -b flags, see the git-svn manpage.

A little naive we could try to push everything to the SVN repository now:

$ git svn dcommit
Unable to determine upstream SVN information from HEAD history.
Perhaps the repository is empty. at /opt/local/libexec/git-core/git-svn line 439.

This fails since the git svn command can’t figure out which commits to push: there’s no link between our original Git repository and the Subversion heads.

To fix this, we can use a Git graft to link them. We’ll tell Git the commit which created the SVN folder in which we want to store the project is the parent commit of the first commit in our Git repository:

$ git show-ref trunk
741ab63aea786882eafd38dc74369e651f554c9c refs/remotes/trunk
$ git log --pretty=oneline master | tail -n1
88464cfdf549a82b30ee7c52e53e2b310f0d9ec4 Initial version
$ echo "88464cfdf549a82b30ee7c52e53e2b310f0d9ec4 741ab63aea786882eafd38dc74369e651f554c9c" >> .git/info/grafts

If now you execute git log, you’ll see the “Create repository structure” SVN commit is displayed after our “Initial version” commit.

Pushing to SVN now works fine:

$ git svn dcommit
Committing to file:///Users/nicolas/Temp/git_to_svn/repo/trunk ...
	A	test.txt
Committed r2
	A	test.txt
r2 = 8c72757dd3a7d550ed8ef393bb74c0350d22dbac (trunk)
No changes between current HEAD and refs/remotes/trunk
Resetting to the latest refs/remotes/trunk
test.txt: locally modified
	M	test.txt
Committed r3
	M	test.txt
r3 = ca0fc06d477bcd4dd5c6f6d2ae6d94356b510280 (trunk)
No changes between current HEAD and refs/remotes/trunk
Resetting to the latest refs/remotes/trunk

All set :-)

Posted in Development, Technology.

Tagged with , , .


13 Responses

Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.

  1. Tchernobog says

    Untested:

    apt-get install bzr bzr-git bzr-svn
    bzr branch git://repo/name repo
    cd repo
    bzr push svn://central.svn.repo/name

    All set?

  2. Nicolas says

    Ah those Bazaar fanboys, got to love them.

  3. Abd4llA says

    Cool,
    now the commit you put in the grafts file is the commit from the original git repo you wanna push to the svn correct ?
    I did that before but using a different way, in the git svn repo I pulled from the original git repo, rebased the git svn, then dcommet the changes to svn. worked fine . but I guess with grafts you don’t have to pull evertime you wanna update your svn. very nice ;)

  4. Gena says

    Awesome,
    this helped me a lot.

  5. Jon Alvarado says

    This helped me thanks.

  6. Steve says

    Hi,

    I’m trying to import the tree structure of a git repos to a svn via the method you provided, but have been encountering the following error.

    “Couldn’t open a repository: Unable to open an ra_local session to URL: Unable to
    open repository ‘file:///d:/test/svn_test/repo’: Expected FS format ’2′; fo
    und format ’4′ at C:\Program Files\Git/libexec/git-core/git-svn line 1765″

    My git and svn are installed in C:/ and the repos are on D:/, a mapped networked shared drive. The stricture of my folder for the repos is as follow.

    test
    ->git-test
    –>working
    ->svn_test
    –>repo
    –>working

    Would appreciate if you cna give me some advise regarding the problem im encountering.

    Regards

  7. ferdinand says

    thanks …. this really helped me.

  8. joost says

    Works perfectly! I recently gave up on trying to convert my coworkers from using git, and this allowed me to revert to using svn for the origin repo.

    I guess my coworkers have a higher tolerance for subversion pain than I do :-)

  9. NN says

    There should be some git command for connecting revisions instead of echo >> .

  10. Martin Gross says

    Exactly what I was looking for. Thanks!

  11. freespace says

    Did exactly what I want – awesome.

  12. Xeross says

    Couldn’t figure out how to do this on my own, thanks for the pointers. Still one would think it should be easier than this :/

Continuing the Discussion

  1. Using svn and git concurrently « Wallento's Random Stuff linked to this post on June 12, 2010

    [...] Initially we want to push our current stuff to the subversion repository. This is not absolutely straight forward, but easily done as described here. [...]



Some HTML is OK

or, reply to this post via trackback.