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.
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 firstname.lastname@example.org: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
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.
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 🙂
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”
Te he he
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?
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.
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.
-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.
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!
What will happen if we don’t execute the “git reset –hard remotes/trunk” command?