Bridging the gap: GIT & SVN, B.F.F.


I’ve been using SVN for several years now, since late 2005 or early 2006, and its done me well since then. But a new darling has entered my life and its name is Git. I like git for some very specific reasons: It’s stupid easy to work with and as good or better then SVN for reliability. Also it helps that my preferred IDE, Komodo, recognizes and works with Git as well.
That said, I use google code for hosting my public projects and it only supports SVN and HG. So one night I read up on git and noticed that it had a plugin/support for bridging to a SVN managed repo. So began my journey.

!Note – I am using a client side credentials manager, if access to your repo requires authentication credentials you will need to supply them where appropriate.


Bridging a new Git Repo to a new directory in SVN
Step 1:

$svn mkdir

Committed revision 26.

Now I’ve got a fresh/empty svn directory

   $git svn init
   Initialized empty Git repository in ~/dev/javascript/cnvLib/.git/

Now I’ve got a local git repo that has most of the information I need for the bridge, to verify everything is hunky dory so far:

    $git svn fetch
    #r26 = a47a908ea96bec2d737f6646c47418778ce6ad32 (git-svn)

Before the graft

Final steps, the graft

Some tutorials out there say you should run git svn rebase or such, but doing so has gone poorly for me with results like

$ git svn rebase                                                                   
      fatal: ambiguous argument 'HEAD': unknown revision or path not in the working tree.                                           
      Use '--' to separate paths from revisions                                                                                     
      log --no-color --first-parent --pretty=medium HEAD: command returned error: 128                                               

I believe the problem relates to lining up your local Git repository with the remote SVN repository. Unfortunately I was somewhat stuck in trying to figure out how the hell to fix this problem for a long time. Fortunately Google search is the modern day version of a genie, it can grant you the information you seek, but first you have to know what to ask. Which led me to finding this blog post.

I am not doing things “exactly” like the aforementioned blog, but close enough that I can get a similar result.

$ git show-ref
2a41e85e0dc264cfdb6c04b59547a3093c02f64f refs/heads/master
a47a908ea96bec2d737f6646c47418778ce6ad32 refs/remotes/git-svn
$ git log --pretty=oneline master
2a41e85e0dc264cfdb6c04b59547a3093c02f64f Initial import, copied from ping project
$ echo "2a41e85e0dc264cfdb6c04b59547a3093c02f64f a47a908ea96bec2d737f6646c47418778ce6ad32" >> .git/info/grafts

After the Graft

Since I am doing things a little odd/differently, there is no “trunk” branch available. But the idea is close enough to duplicate. I’ve already made some add/commit’s to my local Git repo but there isn’t a logical way to tell git/git-svn that this local commit also belongs to my remote SVN remote. A more human friendly version of git show-ref is
available via:

$ git branch -a
* master

So the concatenation of the two internal reference’s into .git/info/graft helps git-svn understand that the two separate repositories belong to each other. Sometimes it’s nice when a configuration structure does what it’s called.

That said, on to the next obvious step, actually pushing changes from a local Git repo to SVN.

$ git svn dcommit
Committing to ...
        A       app.canvas.js
        A       app.input.js
        A       app.main.js
        A       app.mainloop.js
        A       app.shapes.js
Committed r27
        A       app.canvas.js
        A       app.mainloop.js
        A       app.input.js
        A       app.shapes.js
        A       app.main.js
r27 = ae1cd1055deffe4209ab89d1316c97336c731c39 (git-svn)
No changes between current HEAD and refs/remotes/git-svn
Resetting to the latest refs/remotes/git-svn

What’s going on here?

As I am still learning the finer points of Git, it was important to me to understand what exactly .git/info/grafts does. So turning to my favorite resource for arbitrary questions… I found an answer on Stack overflow: What are git info grafts for? And a more official answer in the Git Wiki