I’ve been using git as my favorite version control tool for quite a while now. One of its numerous distinguishing features is an optional component called git-svn, which serves as a bi-directional “bridge” that enables native git repositories to interact with a Subversion repository, performing all the normal operations you would need to use svn for. In other words, since you can checkout, commit to, and query the logs of Subversion repositories (among other things) using git-svn, git can serve as your all-in-one Subversion client.
One reason why you might use git-svn because your project actually resides in a Subversion repository and other people need to access it using Subversion-only tools. Another might be because you have multiple projects, some that use git and others that use Subversion, and you’re tired of switching between svn and git commands—like me. For us, it’s far easier to simply use git as a Subversion client and never have to call svn directly.
As an important aside, please note that I would strongly discourage people who are new to git from learning about it by using git-svn. Although you may think that moving to git from Subversion would be eased by using the git-svn bridge, I really don’t think that’s the case. You’re much, much better off simply using git by itself right off the bat, and you can do this even if your fellow committers are using subversion.
Also, I’m going to assume you’ve already got a Subversion repository set up somewhere.
First, checkout the subversion repository. In Subversion you would do this:
svn checkout http://example.com/path/to/svn/repo
With git-svn, you do this:
git svn clone http://example.com/path/to/svn/repo
This will cause git-svn to create a new directory called repo, switch to it, initialize a new git repository, configure the Subversion repository at http://example.com/path/to/svn/repo as a remote git branch (confusingly called git-svn by default, although you can specify your name by passing a -Rremote_name or --svn-remote=remote_name option), and then does a checkout.
The output of this command will be a little awkward. Here’s a sample from one my repositories:
r14 = dbd7266f328ef2ad061ea4532f39ce7cebaba0c5 (git-svn) M trunk/Chapter 6/Chapter 6.doc M trunk/Chapter 6/code examples/6.1.html A trunk/Chapter 6/code examples/6.2.html r15 = 4cca08341ab0600069cece77ce67afc449caca68 (git-svn) M trunk/Chapter 6/Chapter 6.doc A trunk/Chapter 6/code examples/print.css A trunk/Chapter 6/code examples/screen.css M trunk/Chapter 6/code examples/6.1.html M trunk/Chapter 6/code examples/6.2.html r16 = 7b2f3e0ccfd79be61b527b6ba325f8689475dc01 (git-svn) M trunk/Chapter 5/Chapter 5.doc r17 = a319764855361d92bb6e006cfd18a51319046cae (git-svn) M trunk/Chapter 5/Chapter 5.doc r18 = 4cd5cb43d33b2dd45bd39b9a2b7ea9416f9e3d8f (git-svn) M trunk/Chapter 6/Chapter 6.doc M trunk/Chapter 6/code examples/screen.css M trunk/Chapter 6/code examples/6.1.html
As you can see, git-svn is associating specific Subversion revisions with particular git commit objects. Due to this required mapping, the initial cloning process of a Subversion repository may take some time. This is a good opportunity for your morning coffee break.
When this process is done, you’ll have a typical git repository with a local master branch and one remote branch for the Subversion repository:
Perseus:repo maymay$ git branch
* master
Perseus:repo maymay$ git branch -r
git-svn
You can now treat the Subversion repository as though it were a remote branch of sorts. Say you’ve done a bunch of work and, as you typically do with git, you commit this work to your topic branch.
Perseus:repo maymay$ git checkout -b awesome-feature
Switched to a new branch "awesome-feature"
Perseus:repo maymay$ vim awesome-feature-stylesheet.css
Perseus:repo maymay$ git add awesome-feature-stylesheet.css
Perseus:repo maymay$ git commit -m "Now I'm perty."
Created commit 07ee832: Now I'm perty.
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 awesome-feature-stylesheet.css
Right now your changes are still in the topic branch (called awesome-feature in the above example). To get them to Subversion, you merely need to say git svn dcommit:
Perseus:repo maymay$ git svn dcommit
Committing to http://example.com/path/to/svn/repo ...
Note that pesky extra “d” in the command. This is the equivalent of Subversion’s svn commit, but the commit message used is the one from the previous command, which in this case was git commit -m "Now I'm perty.". Also interesting to note here is that because Subversion doesn’t understand git branches, any change on any branch can be “pushed” to Subversion at any time using git svn dcommit—the git commits don’t have to be on any specific branch, since all git-svn does is map a git commit object to a Subversion revision and vice versa.
Similarly, you can at any time run the equivalent of svn update to get the latest changes from the Subversion repository into your Subversion branch.
- To do this, without affecting your working tree—that is, to only fetch the latest changes but not write them to the filesystem, just to the git-svn metadata area and the remote git branch—use
git svn fetch. To apply these changes to your local branch, you simply merge:git checkout master; git merge git-svn. - If you do want to write out the changes to the filesystem (as
svn updatewould do), usegit svn rebase, which automatically linearizes your local git commit history after the commit history of the incoming Subversion changesets. Very slick.
If your fetching/rebasing causes a conflict, you’ll be notified and will have to resolve it as per usual. If your “pushes” to the svn repo causes a Subversion conflict, you’ll be notified and you should again edit the appropriate files to resolve it, but this time make sure you run a git svn rebase before you try dcommit-ing again (since, remember, Subversion can only handle linear commit history).
As always, saying man git-svn or git help svn to your shell will give you all the other details. Among these, the most likely you’ll probably want to learn about is how to track multiple Subversion branches as normal git branches.
This post is pure gold. I keep going back to refer to it each time there’s an SVN repo I want to abstract into git – and there are a lot of SVN repos. Thanks!
Johnny
25 Sep 09 at 10:19 AM
I’m glad this is helpful for you, Johnny. :D Thanks for being one of the rare good people who come back to say thank you.
Meitar
26 Sep 09 at 3:12 AM
[...] How To Use Git-SVN as the Only Subversion Client You’ll Need at Everything In Between (tags: svn git development) [...]
Steve Mactaggart’s Blog » Blog Archive » links for 2009-10-16
16 Oct 09 at 11:31 PM
[...] a hangover because the tests are very readable and they produce clean verification errors." How To Use Git-SVN as the Only Subversion Client You’ll Need at Everything In Between Wie man Git-SVN als einzigen Subversion client verwenden kann, wenn das Zielprojekt SVN verwendet, [...]
Max’ Lesestoff zum Wochenende | PHP hates me - Der PHP Blog
6 Mar 10 at 1:00 AM
What do ya do if the repo uses svn:externals? It seems that there is not a nice workaround available.
BerT
8 Mar 10 at 3:02 AM
BerT, for a SVN repository that uses
svn:externals, you can use this git-svn-clone-externals tool. I’ve used it in a number of projects that are hosted by a central Subversion repository with multiplesvn:externalsdefinitions in them, and this tool is remarkably straight-forward. Good luck.Meitar
12 Mar 10 at 4:25 AM
Meitar
In the interest of being…
one of the rare good people who come back to say thank you.
…thanks!!!
Carlus
23 Mar 10 at 1:27 PM
[...] How To Use Git-SVN as the Only Subversion Client You’ll Need at Everything In Between great notes for a migrator like me (tags: git, subversion,) [...]
links for 2010-09-14
14 Sep 10 at 5:37 AM
BTW, checking your code for changes:
git svn statusdoesn’t exist for obvious reasons. Aftergit svn cloneyou have a git repository on your disk, thereforegit statusis just fine for checking.Peterino
20 Nov 10 at 10:52 PM
I think git-svn does not synchronize it’s refs or remote branch information across push/pull to, say, a github repo. Assuming this is true, how do I replicate the same git-svn state from machine A to machine B? I want to work on my github repo and git svn rebase changes from upstream SVN from any machine I’m working on. Is this possible? Thanks!
James Dunne
13 Jan 11 at 12:55 PM
I would also like to try the way / workflow James Dunne is suggesting.
Tuomo
9 Mar 11 at 9:31 AM
[...] I heard that you could use git as a svn client, I was intrigued and gave it a fair chance. This is the workflow that I’ve found to be most [...]
A Successful Workflow with git-svn | Object Partners Inc
17 Mar 11 at 10:04 AM
Great info, but the search term highlighting is incredibly distracting.
Am I missing the button/link to turn it off?
Spener
11 Jun 11 at 8:36 AM
Hi, Meitar – thanks for this. It’s one of the most concise and useful versions of the information. One note: I used -Rorigin on the original clone so that I could use “git push origin master”, etc., just as if I were working with Github.
Joe McMahon
3 Aug 11 at 5:26 PM
Thanks a bunch for this post. This answered some of the questions I needed for using Git with SVN repos. Awesome!
Isxek
9 Sep 11 at 3:00 AM
It is 2011 and this post is still awesome. Thanks!
Timur Strekalov
15 Sep 11 at 4:46 AM
[...] How To Use Git-SVN as the Only Subversion Client You’ll Need (a short version) [...]
Using git – first try | I Like Flying
8 Nov 11 at 10:43 AM
Very handy.
Thanks a lot for the clear description.
Yuga
1 May 12 at 12:24 AM
I am trying to use gitsvn to maintain a mirror of an svn repository on github. It works fine if I do it all from one computer, but as soon as I move to a different computer and want to update the mirror, I have trouble. I’ve detailed the problem here:
http://stackoverflow.com/questions/10886784/updating-a-git-mirror-of-an-svn-repository
Could you clarify this use case in your tutorial?
Thanks!
David
David Doria
6 Jun 12 at 8:07 AM
This entry is still useful.
Thanks!!
masaya
18 Sep 12 at 2:48 AM
Thank you for this great post!
Giustino Borzacchiello
6 Dec 12 at 7:27 AM
I would certainly like to follow the good examples of Johnny and Carlus – thanks a lot for this article, Meitar. I would also like to restart the question posted by James Dunne and Tuomo two years ago.
Any opinions anyone?
Nik Ivancic
2 Feb 13 at 12:16 PM
[...] References and further help: http://git.or.cz/course/svn.html http://viget.com/extend/effectively-using-git-with-subversion http://maymay.net/blog/2009/02/24/how-to-use-git-svn-as-the-only-subversion-client-youll-need [...]
DB's Tech Blog - .NET Development, Architecture, Project Management, IVR Systems
13 Apr 13 at 3:54 AM