Creating a two way sync between a Github repository and Subversion

December 3, 2013

git_vs_svn

Another git <> svn post?

As many of you know I have been on a quest to get Jetpack core development moved from the WordPress.org Subversion (svn) repository to Github (git). As part of this process I setup an experimental Jetpack repository to see how synchronization works between git and svn. Lets just clear the air right now and say not well, not well at all. This is due to how git and svn each store their respective histories. But! I think I finally have it figure out.

Backfill

I wrote an article a couple months ago entitled Creating a synchronized Github fork of a WordPress.org Subversion plugin repository. This article is great (and still a recommended read) if you are only doing synchronization between the svn server and a local git repository, but fails miserably when adding in a remote git server such as Github (See note in Ch 8 of the git book). I was worried that true two way synchronization was not possible until I spoke with some helpful folks from Github and Zack Tollman (I.E. Git Master) who recommended I try a branch dedicated to the remote svn connection only instead of trying to mix it into trunk. I am happy to report that this setup has been working flawlessly for a couple months now. I have experienced zero conflicts when performing any syncs and now I want to show you how to set it up as well.

It should be noted that the sync is triggered by you on your local machine. This is not an automated process on Github’s servers, nor will any of the syncing information be available to anyone else who later clones the git repository.

Get your git

I will be utilizing the Jetpack repository I setup on Github for the examples going forward in this tutorial, so the first thing to do is setup yourself a repository on Github where this project will live and then clone it down to your local machine.

git clone git@github.com:blobaugh/jetpack.git

or for those of you not using ssh keys with Github (you really should)

git clone https://github.com/blobaugh/jetpack.git

(Sidenote: Ironically you can also checkout from Github via svn with the https address…)

You will use trunk and development branches here as normal. Feel free to do all the pushes and pulls to Github that you desire, however do not hook up trunk or any development branches to the Subversion repository!

Setup an svn tracking branch

The next step is to create a branch that will only be used to setup a remote connection to the Subversion server. You will never do any development changes directly in this branch. If you do you will most likely encounter severe issues due to the incompatible histories of both systems. Instead you will be using git’s merging features between branches.

git branch --no-track svnsync
git svn init -s http://plugins.svn.wordpress.org/jetpack
git svn fetch
git reset --hard remotes/trunk

(Sidenote: If you are syncing also author profiles you can add

--authors-file svn-authors.txt

to the fetch command. I will update this tutorial with details on the author file later)

 Do your business

You are now all setup to begin developing your amazing whatever with full confidence that changes made to the git or svn side can and will safely be reflected back to each other. But wait! Keep reading now to find out the tricks to make the sync work after you have created those amazing new additions to your project.

Merge changes back from svn into Github trunk

First all changes from svn are going to be merged locally and staged to be pushed out to the Github repository.

git checkout svnsync
git svn rebase
git checkout master
git merge svnsync
git push origin master

Merge changes from Github trunk into svn

Now going the other direction. This is a bit more complicated than pulling in from svn, but make sure you follow all the steps or you will get nasty errors with the sync. Keep in mind the –no-ff on the merge is very important to include. We also want to make sure everything is fully updated from both Github and the svn server before performing the push to svn.

git checkout master
git pull origin master
git checkout svnsync
git svn rebase
git merge --no-ff master
git commit
git svn dcommit

The order of the commit and dcommit is important here. Switch them and the histories will conflict.

Drink Scotch

This is the happy point when everything is working lovely and you get to drink Scotch to celebrate!

And if something went wrong and you are freaking out an anxiously scratching your head I also recommend Scotch 🙂

Resources

Here are a few resources that helped in writing this tutorial:

8 thoughts on “Creating a two way sync between a Github repository and Subversion

  1. Ben Lobaugh Online » Creating a synchronized Github fork of a WordPress.org Subversion plugin repository
  2. Daniel Bachhuber (December 4, 2013)

    Te he he

  3. André (March 12, 2014)

    I have multiple working locations and on every location I need to have a two way sync for the same SVN/Git. On every location I would checkout the Git repository and the svnsync branch according to your tutorial. But how I can refresh the Git on the second location, if I have changed git/svn (the head moved on) on the first location?

    1. Ben Lobaugh (blobaugh) (March 13, 2014)

      You will need to setup a git remote that points to whatever other repository you need to pull from. The easiest way to do this is to treat on as the central repo, or origin. This is the model Github uses.

  4. Brice T (April 29, 2015)

    Thanks for this how to !
    I may be wrong, but I guess there is a missing `git checkout svnsync` before the `git svn init …`.
    Moreover, I can not find what the -s means for this git svn init. I am now running git 2 and it may have changed … ? Whatever, I removed the -s to get things working.

    1. Sebastian (March 1, 2016)

      -s means “standard”. Adding the flag you’re saying to Git that your SVN repository has a standard structure (trunk, tags and branches).

      Thanks for the tutorial, It was really helpful.

  5. Gary Woodfine (July 13, 2016)

    Thanks so much for taking the time to post this series of posts. Also providing the links to the numerous other blog posts regarding this subject!

    I have been messing about with this for a few days now, and trying to get it work. Reading your posts and the links you’ve provided have definitely provided me with enough background now. I will return the favour to the community by writing yet another blog post to document my findings!

  6. Arjit (September 22, 2017)

    What will happen if we don’t execute the “git reset –hard remotes/trunk” command?