Everything In Between

If your project so much as pretends to have a profit motive, I will tell you to go fuck yourself and your project.

How To Use Git-SVN as the Only Subversion Client You’ll Need

25 comments

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 update would do), use git 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.

Written by Meitar

February 24th, 2009 at 1:17 pm

25 Responses to 'How To Use Git-SVN as the Only Subversion Client You’ll Need'

Subscribe to comments with RSS or TrackBack to 'How To Use Git-SVN as the Only Subversion Client You’ll Need'.

  1. 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

  2. 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

  3. […] How To Use Git-SVN as the Only Subversion Client You’ll Need at Everything In Between (tags: svn git development) […]

  4. […] 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, […]

  5. 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

  6. 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 multiple svn:externals definitions in them, and this tool is remarkably straight-forward. Good luck.

    Meitar

    12 Mar 10 at 4:25 AM

  7. 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

  8. […] 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,) […]

  9. BTW, checking your code for changes:
    git svn status doesn’t exist for obvious reasons. After git svn clone you have a git repository on your disk, therefore git status is just fine for checking.

    Peterino

    20 Nov 10 at 10:52 PM

  10. 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

  11. I would also like to try the way / workflow James Dunne is suggesting.

    Tuomo

    9 Mar 11 at 9:31 AM

  12. […] 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 […]

  13. 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

  14. 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

  15. 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

  16. It is 2011 and this post is still awesome. Thanks!

    Timur Strekalov

    15 Sep 11 at 4:46 AM

  17. […] How To Use Git-SVN as the Only Subversion Client You’ll Need (a short version) […]

  18. Very handy.
    Thanks a lot for the clear description.

    Yuga

    1 May 12 at 12:24 AM

  19. 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

  20. This entry is still useful.
    Thanks!!

    masaya

    18 Sep 12 at 2:48 AM

  21. Thank you for this great post!

  22. 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

  23. It’s 2014 and this is still the best guide around to git svn.

    Thank you got sharing this with us!

    Cristian

    7 Jan 14 at 5:52 AM

  24. I’ve been doing this for several months now and this is probably one of the better write ups I’ve found. I’ve found that it’s important to git svn rebase before every git svn dcommit which could just be a peculiarity of my environment but I have the least heartache as a result. I’ve also been able to push the code out to github so this method has been essential in my plan to migrate my team off of SVN altogether.

    Thanks for taking the time to document this.

    Mikel King

    15 Apr 14 at 12:55 PM

Leave a Reply