A while back I wrote an article on WP.Tuts on using Git to publish plug-ins on the WordPress repository. The wordpress.org plugin repository runs on Subversion, but I, for various reasons prefer to use Git. It’s also incredibly useful for putting your plug-on GitHub or BitBucket where you can collaborate with other developers.
The trouble is two-fold:
- Git & SVN don’t play particularly nice
- My local (and Github) Git repository are focussed on development, the wordpress.org is solely for distribution.
Let me explain the second point a bit more. If you’ve worked with Git you’ll probably be aware that you are to commit little and often (see for example, Tom McFarlin’s recent post). But the WordPress repository is for distribution – they don’t need or want all the those commits.
In fact, as you probably know, Otto has said:
“If I catch you at it [pushing each commit separately], then I will ban you from WordPress.org. The SVN only needs your final working version committed to it, not the entire history of the hundreds of changes you made using Git. Flatten your changes to a single commit.”
Now in my original article I outlined a workflow in which you develop in a ‘development branch’ and then when ready to release something, merge and squash those changes into your master, before pushing to the SVN. Unfortunately, beyond you current ‘development branch’ you loose all your history.
A Better Workflow
I’m not sure why this didn’t occur to me earlier, but by essentially reversing this workflow, we can preserver our history, but also commit to the WordPress subversion times only once or twice for each tagged release. We do this by developing in the master (or some other branch), and merge and squash into a release branch. We push from the release branch to the SVN repository.
This isn’t actually different from what we were originally doing since from a git point a view (but not a Github point of view) the master branch is just another branch. But we do need to set up our release branch to track the remote SVN repository.
How It Works
(I’m posting this as much for my own reference as anything else). I’ll assume that you’ve been working on a project for some time, and let’s suppose its in Github, but now you want to publish it to the WordPress repository. Once you’ve been accepted you’ll receive an e-mail containing a link to your wordpress.org hosted SVN repository, something like
Step 1: Clone the SVN Repository
The WordPress repository is big, to clone our plug-in we’ll first tell git where to find it. The following will get the first log of our SVN repository (when it was originally added):
svn log -r 1:HEAD --limit 1 http://plugins.svn.wordpress.org/your-plug-in-name
It will think for a while and then you should see something like this:
r651844 | plugin-master | 2013-01-13 05:33:38 +0000 (Sun, 13 Jan 2013) | 1 line
rXXXXXX (revision) number is what we’ll use to ‘find’ our repository. It’s not necessary, but speeds things up somewhat. So next we clone our repository:
git svn clone -s -r651844 --no-minimize-url http://plugins.svn.wordpress.org/your-plugin-name
This should take a few minutes, but it will initialise a git repository with the folder
your-plug-name. Let’s view the branches in that repository:
cd your-plugin-name git branch -a
This should list master (your local repo – this will probably be starred as its the branch you’re in currently). As a remote repository it will also have (the SVN) remotes/trunk. Currently our repository is empty (since our plug-in’s SVN repository is). (If it wasn’t we could fast-forward through the changes and have an up-to-date copy.)
Step 2: Pull Our Project From Github
Our plug-in is currently sitting on Github, so the idea is to pull it into our newly created repository. So let’s add our Github repository (which I’ll call
origin – but it can be anything) and then pull it into our repo:
git remote add origin firstname.lastname@example.org:your-github-username/your-repo-name.git git pull origin master
Our plug-in should now be in our repository, along with its complete history. We can commit further changes if we desired.
Step 3: Create A Release Repository
Next create, and checkout our release repository:
git checkout --track -b release remotes/trunk
This now tracks our SVN trunk sitting in the WordPress Repository. Everything is now set up. We can return to the master branch and make any changes if desired.
Step 4: Committing to SVN Trunk
Let’s suppose we’re ready to push to the SVN branch the latest and greatest changes we’ve made in our master branch. We checkout our release branch and merge (and squash!) our master branch
git checkout release git merge --squash master
Note: after the first merge you’ll notice that you start getting merge conflicts – assuming you don’t develop on the ‘stable’ branch, these aren’t really conflicts at all, and its much easier to do the following which is the same as the above, but any ‘conflicts’ are automatically resolved in favour of the master branch:
git merge --squash -Xtheirs master
Just to be sure we don’t loose anything on SVN we can perform a rebase (though I find this is never necessary and if you’re the only commiter you’ll probably find this too)
git svn rebase
Hopefully you’ll get a message saying Current branch master is up to date. Then we’re ready to push:
git svn dcommit
This may take a few minutes.
Step 5: Tagging A New Release
Our trunk is now up to date, but if we were tagging a new release (and so had updated the plug-in’s readme.txt stable tag) we also need to create that tag. This is very simple, for tagging “1.6.1” for instance:
git svn tag "1.6.1"
Again, this may take a few minutes. You shall probably receive an e-mail notification from WordPress.org too. In about 5 minutes time the WordPress plug-in repository should be updated with your new release.
I hope this helps! If you’ve any suggestions on better workflows, I’d love to hear about them, so please leave a comment :).