As discussed earlier on this site, I recently started using git in our svn centric organization. Since I’m trying to convince some co-workers to do the same, I would like to share a bit of git voodoo for working with multiple git repositories and a central svn repository. Most git tutorials don’t really show how to do this, even though it is quite easy. The approach below gives you all the flexibility with git that you need while allowing you to inter-operate seamlessly with your svn using colleagues.
Before getting started, make sure you have both git-core and git-svn installed (ubuntu) or that you have done a “sudo port install git-core +svn +bash_completion” if you have a mac. Also, you probably want to configure git properly. Google is your friend, there are plenty of tutorials on the basics of git and svn that you might want to run through first.
Both git and svn use urls to identify repositories. For the sake of simplicity, I will use a very basic example involving three local repositories on my file system with file:// based urls but of course you can use http:// ssh+svn:// or git:// type urls just the same:
- file:///Users/jilles/test/svnrepo - A little svn repository. Generally this will be your central svn repo with years of work inside it.
- file:///Users/jilles/test/git1 - A git repository that we’ll create using git svn.
- file:///Users/jilles/test/git2 - Another git repository that we will create using git clone.
Lets start by creating a simple svn repo, checking out a svn work copy, and committing some stuff using svn:
Ok, we now have a svn repo with some stuff in it. In the git world, you always work on a local repository. You don’t check out from a remote repository, instead you clone it. So, lets git svn clone it to a local git repository and make some changes there and then commit it back to the svn repo:
cd /Users/jilles/test/ # clone the svn repository to a git repository using git-svn ... git svn clone file:///Users/jilles/test/svnrepo git1 cd git1 # observe there is a hi.txt and a .git directory. here echo " World" >> hi.txt # stage a change. git add hi.txt # now commit the change to your local git repository (i.e. your .git directory contains it) git commit -m"say hi to the world" # and finally push the local change back to svn git svn dcommit
Now lets check on the svn side if it worked …
Yup, our change is there.
Now imagine a co-worker comes along, who wants to work on his own git repository: git2. To get started, he clones the existing git1 repository and right away makes some changes.
Back to git1, who is of course interested in the change made in git2:
Git1 and Git2 now have the same change but it is not in svn yet. Git2 can’t commit to svn yet. So, lets fix that. Open /Users/jilles/test/git2/.git/config in an editor and append the following section:
Save the file and:
Good, the change is now back in svn. Lets verify and modify some more in the svn world:
And lets rebase git1 and git2 against svn:
Now git1, git2, and svn are in sync and have the same history. If you examine the history with git log on git1 and git2, you will notice that all the commits have the same hashes. This is no coincidence, commits have globally unique sha1 hashes that are based on their content. The same changes will yield the same hashes no matter where you make them. This is the reason git works so well. It doesn’t matter where the change came from, as long as the hashes line up, everything will be fine.
I’ve demonstrated that git1 and git2 can pull changes from each other and that you can rebase and dcommit against the central svn repository. You needn’t be afraid of double commits or lost commits. Git all sorts it out. From git’s point of view, a central svn is just another repository. Git is decentralized and throwing svn in the mix doesn’t make much of a difference. It just integrates more or less seamlessly. So, you and your git using co-workers can go off and do all the cool stuff git users do, while all staying in sync with the central svn repository.
Random things you probably want to play with next:
- git svn clone your svn repository; or git clone it from one of your git using colleagues and manually add the svn remote
- use git daemon to set up a network daemon that your colleagues can pull changes from remotely
- create a local branch and integrate changes from your colleagues there before merging back to your git master and dcommitting the change to svn
- allow others to pull your experimental branch