I recently started using Git and have been super impressed, so I thought I’d write up a few thoughts on using it for website versioning and deployment. I’ll begin at the end of the process (where better?) – setting up post-receive
hooks – and cover the more basic setting up some other time. Mainly because while the whole process of using Git feels a little like magic, this bit is by far the most magical.
A few brief words about where I’m at and what set-up I use. Other than this site, which is at GitHub Pages, I use nearlyfreespeech.net for my hosting. I really can’t recommend them enough – I hesitate to use the word cheap, because I think it sends the wrong message, so instead I’ll say that they are one of the very few hosts that I consider reasonably priced for small-scale sites. Everybody else screws you.
NFSN are pay-as-you-go, whereas most hosts charge a monthly rental fee. It’s true that if you used every last drop of storage and bandwidth of your monthly allowance, your costs would probably be lower per unit elsewhere – but there is essentially a 0% chance of that happening for anybody not running a high-traffic blog or similar. To put things in perspective: the cheapest alternative host I have found costs as much for one site, for one month, as NFSN costs me for all my sites, for an entire year. They also offer SSH as standard, no questions asked.
One last comment in this extended NFSN advert (I swear they don’t run an affiliate programme): you might be put off by their lack of 24/7 support. In my time online I’ve run into a few problems with webhosts. These things happen. With other hosts – who allegedly do offer support – it often took days to get a response, and weeks to get anything done about the issue. Quite literally weeks, during which time the site in question was totally offline.
In my entire time with NFSN, I have had one problem. I put up a message on their support forum, and had a response within an hour. The next morning the issue was fixed. The only reason the fix came the next morning was the time-zone difference: if I lived in the States I’d have seen it by the end of the day. That’s how you do support.
I discovered Jekyll just after I had finished doing a big overhaul of the back- and front-end of the View from Nobody, including moving the whole site to WordPress and building a custom theme from scratch. Talk about great timing. The short version of the story is that Jekyll is the bomb, and as soon as I have time I’ll be porting the site over to it. In the meantime, Git is still pretty helpful – particularly during updates, given that I customise some of the core. I was going to set up automatic syncing of the database as well, but then I just got on with my life.
For now, I have most of my sites running on Jekyll, and one running on WordPress. I use different post-receive
hooks in each case, so I’m splitting this into two parts. The WordPress version is more straightforward (they’re both pretty straightforward) so I’ll cover it first.
Last note: I’m on Windows. I expected this to be a massive headache, but thanks to the shell included with GitHub for Windows, it’s actually not been a big deal.
There are three basic directories on NFSN:
public
, which does exactly what you’d expect (equivalent to the www
directory that some other hosts use);
private
, which is roughly equivalent to your home
folder on a *nix set-up (appropriately, it’s available at $HOME
in shell scripts, which is a nice touch);
protected
, which I have no idea what it’s for. Storing .htpasswd
files, maybe? That kind of thing? Dunno. I’ve never found a use for it.
Just to point out, all three of these reside in a root folder called home
, so be aware that /home
and $HOME
are not the same – the latter is actually /home/private
. Clear?
I’ve seen a couple of people who, when using Git for deployment, simply make the public
folder a repo. No doubt that makes deployment easier, but it seems a little untidy to me – and is potentially a security risk if people start sniffing around for .git
. So I set up the remote in my private
folder, and take it from there.
I do have one minor gripe about NFSN: they don’t offer on-the-fly server-side compression. Whether it’s because they don’t charge for server cycles or do charge for bandwidth, I don’t know. That means that if you want to serve up your site Gzipped (and you definitely do, right?) then you need to come up with some other kind of solution.
Since WordPress generates its PHP pages on the fly, there’s not an easy answer. Maybe there’s a plug-in that generates compressed pages in parallel? Probably. For the sake of a few bytes (and given how little traffic I get) I have better things to do with my life. I include a pre-zipped version of the CSS and JavaScript files. That could probably be automated but I haven’t looked into it.
With Jekyll, since the static HTML is generated at compile-time rather than run-time, you can do the Gzipping as part of the post-receive
process. More on which in part two.
Finally, the main event. Here’s the whole thing in its ten-line entirety:
Nothing too complicated. At this point I’m assuming there is already a remote for your local development repo in $HOME
. The words version of what this does is as follows:
Delete everything that’s currently in the public
folder;
Clone the repo from $HOME
into the public
folder;
There is no step three. Actually, there is: remove all of the Git-specific files.
Hello this is a shell script so please, like, use Bash.
Delete everything in the public
folder.
The previous command ignores dot-files and -folders, so we need to specifically instruct it to remove the .htaccess
file. I have multiple such files throughout the directory structure, but the others are all removed when their non-hidden directories get the axe. If you have other dot-files in the root of public
then you’ll also need to specify them.
Clone the repo, so that public
now includes an up-to-date version.
Remove the .git
directory. I’m not sure that this actually needs to be split into the two steps above rather than just:
But hey. Other people seem to do it this way, and since I don’t know what I’m up to really I’m just going to go along with that. If you were just using public
as the remote, this wouldn’t be possible without breaking things, hence the point in keeping the repo in $HOME
.
Remove the other Git-specific files that don’t need to be there. Again, if you don’t include a README
, or do include other files, you’ll need to tweak this step to fit your needs.
Presumably I don’t need to explain this step.
So there you have it. A nice and easy post-receive
hook that is perfect (according to my low standards) for deploying WordPress but could easily be applied to other CMSs or the like. Next, we do the same for a Jekyll-based deployment (which is much more fun
).