Using Git Subtree to Pull Out New Plugins

In the post about my development workflow I didn’t explain why I decided to track the entire website instead of just parts of it. Since I’m not doing any development of the WordPress core itself, the option exists to just track my own plugins and themes by creating a new git repository in their directories. I decided against that for a few reasons.

My creation of a branch dedicated to transferring to and from the live server gives me an easy way to see what has changed during the sync operation by comparing to master, for example. The biggest reason though is that I would rather manage branches than a bunch of separate repositories. I can create a branch for a new plugin, work there for a while, do my commits, and then switch to another branch to work on another. I don’t have a bunch of individual repositories each on their own branch. “Oh was that one on master, or feature 1?” Also, if I ever have a bigger project I can have one main branch for several sub-features. It just seems a lot simpler to me to have one repository and use branches.

One shortcoming is that plugins and themes are, by nature, meant to be shared between projects. That’s where the git subtree comes in. Subtree lets you track a subset of the working directory right within your main repository.

Once a new plugin or theme is done, you can tell subtree to create a set of commits that represents just the changes in one particular sub-directory. You can even pull out just that portion of the code and make a new repository from it, and use that new repository as a ‘remote’ from which to pull (or push) code updates. There are already many good articles about subtree so I’m just going to show you the commands I used for my configuration plugin, QnD Dashboard Actions (which I’ll write about eventually).

#in a directory outside the website (let's say it is /shared-repos)
$ mkdir qnd-dashboard-actions
$ cd qnd-dashboard-actions
$ git init #not using --bare since I want the files to be in here
#we have to set a configuration variable here to allow us to push later
#***see below for more info
$ git config --local receive.denyCurrentBranch warn

#now back in the website directory (and thus the main git repo)
#this makes a new branch with just a subset of files tracked
$ git subtree split --prefix=wp-content/plugins/qnd-dashboard-actions -b dashact-split

#make a remote for the shared code. use the full path to
#the directory we created in the first part
$ git remote add shared-dashact /shared-repos/qnd-dashboard-actions

#push the code to the shared repo we made in the first part
#use the -u flag to tell git to make that repository
#the split branch's parent/up-stream
$ git push -u shared-dashact dashact-split:master

There we go. We have our plugin off in its own repository and we can even pull from it if it changes. We just need to make sure to always supply the --prefix= option on our commands. The way I’ve done it here we even have all of its commit history with it. If you don’t want all the history in one or the other locations you can always use the --squash option when splitting, pushing, or pulling.

***I want to point out what this $ git config --local receive.denyCurrentBranch warn is all about. Imagine you’ve got a repository and it is sitting on the master branch. Another repository pushes to the first, onto the master branch. Now the HEAD of the repository looks a certain way, maybe files were added or changed, but the working directory still looks the way it did the last time you checked out master. Things could get ugly for the next guy working on that repository. If you don’t change this config option to warn then git won’t let you push there, when the remote is on the branch you are pushing to. If you have a repository that will be pushed to, always make sure checkout master or do a git reset before you do anything else. If you don’t expect there to ever be development directly in the shared directory then it shouldn’t be a problem.

Comments are closed.