Thursday, December 13, 2007

Using Git with SVN

I've been setting up a git repository to help aid collaboration on the port of restful_authentication to merb as merbful_authentication.

This is such a good library and I use it in all my rails sites that need authentication. It just works and I like that. All credit to Rick Olson for such a great plugin. Hopefully we'll be able to to a good job porting it.

Initially I setup a git repo with this. I'm starting to do most of my work in git so this is a good opportunity to keep going learning it.

You can get the WIP on this plugin via
git clone http://snatcht.com/git/merbful_authentication.git
# OR
git clone git://snatcht.com/git/merbful_authentication.git
This is really just a blank Merb app that has the beginnings of a port in it. There were so many people working on a port of this plugin I figured we might as well work on it together.

To include everyone in the development I needed to have svn as well. Rubyforge have been generous in approving a project for me.

The issue was, how to bring the svn into my local git repo so that I can push changes up to svn. Heres how I did it.
git clone git://snatcht.com/git/merbful_authentication.git

cd merbful_authentication.git

mate .git/config
In this file I put the following
[svn-remote "rubyforge/trunk"]
url = svn+ssh://username@rubyforge.org/var/svn/merbful-auth/trunk
fetch = :refs/remotes/rubyforge/trunk
Then to get the SVN linked into my local git
git-svn fetch rubyforge/trunk

git branch -a
* master
origin/HEAD
origin/master
rubyforge/trunk
You can see that rubyforge/trunk is now present in my git remote branches. Next create a branch from rubyforge/trunk
git checkout -b local-svn/trunk rubyforge/trunk
This will create a local branch that you can use in git like any other branch. Now once you've made changes to your app. Merge them into the local-svn/trunk then update your svn repo with a lazy
git-svn dcommit
from within the local-svn/trunk branch.

12 comments:

toolmantim said...

You know what would be super cool... using a post-commit hook on the remote git server so any push to it triggers a merge and dcommit to the rubyforge SVN. It's as simple as chucking a ruby script in hooks/post-commit and chmoding it to +x. The post-commit hook gets two command line arguments: the commit_sha1 and the branch_name. You'll wanna check the branch_name is master

-- gitmantim

rick said...

Oh hey, why not just ask for a branch on git://activereload.net/restful_authentication.git ? :) (kidding, i _just_ set up git-daemon access an hour ago, but you are totally welcome to commit rights)

Dr Nic said...

@rick + hassox - thx to the wonders of distributed SCM, it could be pushed to a branch of restful_auth.git as well! Yay for advances in space technology!

Dr Nic said...

Arbitrary comment just so I can login via OpenID instead of my blogger ID.

Daniel Neighman said...

@drnic, @rick has set me up with a branch merbful_authentication in the restful_authentication.git repo.

I'm hoping that I'll get the WIP up there soon

Dr Nic said...

Perhaps post your finished .git/config file when you've set up the git-svn + remote git repo.

Dr Nic said...

I had a git repo that I thought to push to a fresh svn repository. I create the svn, added trunk/branches/tags, and then added the .git/config line mentioned above (modified the ssh+svn url obviously).

Then I "git-svn fetch rubyforge/trunk" and I get the following error:

$ git-svn fetch rubyforge/trunk
Migrating from a git-svn v1 layout...
Data from a previous version of git-svn exists, but
.git/svn
(required for this version (1.5.3.5) of git-svn) does not. exist
Done migrating from a git-svn v1 layout
[svn-remote "rubyforge/trunk"] unknown

Despite this warning/error message, a .git/svn folder is created.

If I run the command again, it says just:

[svn-remote "rubyforge/trunk"] unknown

Less verbose, but just as unhelpful.

Thoughts?

PS. Blogger is anti-code - doesn't allow < code> nor < pre> tags :(

Dr Nic said...

Ok, my bad - turns out I hadn't saved the .git/config file...doh.

So, the fetch worked. And the "git checkout -b local-svn/trunk rubyforge/trunk" worked.

Then I "git rebase master", and then attempted the "git dcommit" but got:

Use of uninitialized value in concatenation (.) or string at /usr/local/bin/git-svn line 381.
Committing to ...
Unable to determine upstream SVN information from HEAD history

If, from the local-svn/trunk branch, I try "git-svn rebase" I get:

Unable to determine upstream SVN information from working tree history

Am I missing a step?

Dr Nic said...

Ok, all fixed.

I destroyed the local-svn/trunk branch and started it again.

After "git checkout -b local-svn/trunk rubyforge/trunk" I did a "git-svn rebase". Although there is nothing in the SVN @ this stage, it seemed to do the trick and I get a positive message:

Current branch local-svn/trunk is up to date.

Then I merged across the master branch "git merge master" and then did the dcommit "git-svn dcommit" and happy times!

Thx for the article - I've wondered how to set this up for ages, without having to start with the svn first, and create the git repo 2nd.

Daniel Neighman said...

@drnic seems your all fixed before I read your comments. :) Glad you got it going.

Markus said...

Good job! :)

Ritesh Raj Sarraf said...

I have used your workflow to take care of the svn repos in git. And I have really liked it so far.

Thank you for this write-up.