In the past, I’ve written extensively about using Git with WordPress projects. I’ve focused primarily on Git as the primary development channel, with SVN (in this case, plugins.svn.wordpress.org) used for distribution only.
In contrast, I use Git for all my local development on the BuddyPress project. In this case, BP’s “official” history is in its SVN repo. My local Git repo is just a mirror. This setup means that you need a different kind of workflow, one that gives precedence to the Subversion repository. I’ll be using BuddyPress as an example below, but a similar workflow will work for any Subversion-based project where you want to do local development in Git.
(Side note: Mark Jaquith published a similar guide on how he uses Git to do WordPress core development. His process and mine are independently derived, but they are, of necessity, conceptually similar.)
Setup
- Get Git.
- Create a local directory for your BuddyPress installation. Use git-svn-clone to pull the SVN revision history into this directory.
$ mkdir /path/to/wordpress/wp-content/plugins/buddypress
$ git svn clone -T trunk -t tags -b branches http://buddypress.svn.wordpress.org /path/to/wordpress/wp-content/plugins/buddypress
Git will crawl through the entire revision history of the BuddyPress project, which will take a while.
- I generally have two active, ongoing branches in my local BP-Git repo, one corresponding to
trunk
and one corresponding to the current bugfix branch. I use master
(the default Git branch) for trunk
, since that’ll be the default setup after the clone. You’ll need to create the bugfix branch manually. I use the ‘1.6.x’ naming convention for the 1.6 SVN branch, etc.
$ cd /path/to/wordpress/wp-content/plugins/buddypress
$ git checkout -b 1.6.x 1.6 # In other words, create a new branch, called 1.6.x, which tracks svn's 1.6 branch
- If you’ll need to do development using BP’s bbPress 1.x implementation (“Group Forums”), you’ll need to manually download bbPress 1.1 into
buddypress/bp-forums/bbpress/
Development
Day-to-day development goes something like this:
- Make sure you’re on the right branch. Most day-to-day dev happens on trunk/master, but in some cases it’s necessary to work on the current bugfix branch. Once you’re on the right branch, make sure that you have no unstaged changes, and use git-svn-rebase to get the most recent changes from upstream:
$ git checkout 1.6.x $ git svn rebase
- Create a new topic branch for this bugfixing session. I generally name it after the ticket number.
$ git checkout -b bp4453
- Fix your bug or develop your feature. Commit small changesets as desired.
- When you’re done with your development, you’ll be in one of the following situations.
- You’ve fixed the issue, and want to merge your commit history directly back into the public branch. This generally means that you fixed everything with a single changeset, or perhaps a small number of changesets that have good commit messages, etc. In that case, you can do a straight merge back to the public branch. Switch back, git-svn-rebase to make sure none of your collaborators have updated the SVN branch since you started working, and then merge.
$ git checkout 1.6.x $ git svn rebase
$ git merge bp4453
- You’ve fixed the issue, but you want to reduce a large number of changesets to a single commit. You have a few options here. You can use
git rebase -i
like Mark suggests. I generally do not do this, because rebasing on publicly shared SVN branches makes me nervous. Instead, in these cases I’ll use a squashed merge, which lays all of your changes on top of the destination branch, and leaves them uncommitted.
$ git checkout 1.6.x
$ git merge --squash bp4453
$ git commit -m "This is the actual commit message I want to show up on BP's SVN"
- You want to share your changes with others, in the form of a patch, before committing to SVN. You’ll need to use the
git diff
utility, while doing a formatting trick to make sure that it’s compatible with the standard UNIX patch
utility used in the SVN world.
$ git diff --no-prefix 1.6.x...HEAD > ~/path/to/patches/4453.01.patch
- Assuming you are ready to send some commits up to SVN:
$ git svn dcommit
- In some cases, you may have sent a commit to the bugfix branch that needs to be applied separately to the main dev branch (trunk). There’s a couple different ways you might handle this. I usually use
git-cherry-pick
:
$ git checkout master
$ git svn rebase
$ git cherry-pick e1f2e3f # The hash of the Git commit on the bugfix branch
$ git svn dcommit
Releasing
Releases follow a regular tag workflow:
$ git checkout 1.6.x
$ git svn tag 1.6.2
We do some weird stuff with BuddyPress (related to mirroring on wordpress.org/extend), which is outside the scope of Git – sadly I have to use svn for some of it :'(
Some of this is specific to BP, but most can be applied to any project where you want to use Git on a project that lives in SVN. Now git out there and git er done! and other ‘git’ puns.