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:
- http://ironymark.diwan.com/2011/04/a-safe-way-to-keep-a-github-and-svn-repository-in-sync/
- http://danielbachhuber.com/2012/09/30/git-in-my-subversion/
- http://teleogistic.net/2011/05/revisiting-git-github-and-the-wordpress-org-plugin-repository/
- https://ben.lobaugh.net/blog/90633/creating-a-synchronized-github-fork-of-a-wordpress-org-subversion-plugin-repository
- http://stackoverflow.com/questions/1632165/svn-how-to-get-the-first-revision-of-a-file
- http://jausoft.com/blog/2009/07/08/svn-to-git-migration-1/
- https://github.com/JohnAlbin/git-svn-migrate
- http://john.albin.net/git/convert-subversion-to-git
- http://stackoverflow.com/questions/13956772/git-rebase-branch-on-git-svn-repo-changed-remote-tracking-destination