Setting Up and Automating My Hugo Blog Deployment to GitHub Pages

Update

This is largely obsolete. I have set up a new process to deploy to Amazon S3, and I recommend it over GitHub Pages.

I’m currently moving my blog posts (and collecting entries from various blogging platforms) into Hugo. In case you’re wondering how I’ve set mine up, here’s a guide to what I’ve done.

Choosing the hosting platform

Setting up the blog

Setting up the GitHub Pages

There’s a really cool guide in the official Hugo documentation, and I advise everyone to check it out.

git checkout source

# Delete the master branch
git branch -D master
git push origin :master

# Create an orphaned master branch
git checkout --orphan master
rm -rf *
git rm --cached $(git ls-files)

# Grab one file from the master branch so we can make a commit
git checkout source .gitignore
git commit -m "INIT: initial commit on master branch"
git push origin master

# Return to the source branch
git checkout source

# Remove the public folder to make room for the master subtree
rm -rf public
git add -A
git commit -m 'remove stale public folder'

# Add the master  branch of the repository.
# It will look like a folder named public
git subtree add --prefix\
	public git@github.com:parasquid/parasquid.github.io.git master --squash

# Pull down the file we just committed. This helps avoid merge conflicts
git subtree pull --prefix=public origin master -m 'merge origin'

# Add the CNAME
touch public/CNAME
echo "life.beyondrails.com" > public/CNAME

Scripting the deployment

Again, I referred to the Hugo documentation on setting up Hugo for GitHub hosting and used it as the basis for my own deployment script.

My workflow, however, is unlike any of the three recommended workflows (it’s more like a hybrid):

In the end I went for a git subtree pull before regenerating the blog. And never trying to touch the master branch.

However, the git subtree command is only present in Git version 1.7.11. Ubuntu Precise (12.04) only comes with 1.7.9.5, so in order to use this, a PPA must be installed:

  deb http://ppa.launchpad.net/git-core/ppa/ubuntu precise main
  deb-src http://ppa.launchpad.net/git-core/ppa/ubuntu precise main

While trying to do deployment I ran into numerous problems with errors like:

error: failed to push some refs to
       'git@github.com:parasquid/parasquid.github.io.git'
hint: Updates were rejected because a pushed branch tip is behind its remote
hint: counterpart. Check out this branch and integrate the remote changes
hint: (e.g. 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

Apparently, this message comes up when you already have files in the remote branch and, for some reason, pushing will cause a merge conflict. Eventually, I settled on a bit of brutish action: deleting the master branch and recreating it as an orphan branch for every deployment. I’m not sure if this is something GitHub will frown upon; it’s okay to delete and recreate branches, but since this is a hosted page, it may screw up their bots trying to retrieve the latest version of the branch (since I’m messing up with Git history).

In order to delete the master branch, some preliminary work is needed. GitHub does not allow you to delete the default branch (which is master), so you’d first need to set the default branch to something else and then delete master. Matthew Brett has a very good article that explains the procedure in full.

The downside here is that the site goes down for around 30 minutes every time there’s a deployment. :( Not cool. So I had to look for a different way.

After struggling for quite a few hours, this is the best I can come up with:

#!/bin/bash

echo -e "\033[0;32mDeploying updates to GitHub...\033[0m"

git checkout source
git pull origin source
git add -A
git commit -m 'committing work in progress'

# Pull down the file we just committed. This helps avoid merge conflicts
git subtree pull --prefix=public origin master -m 'merge origin'

# Build the project.
hugo -t hyde-x

# Add the CNAME
touch public/CNAME
echo "life.beyondrails.com" > public/CNAME

# Add changes to git.
git add -A

# Commit changes.
msg="rebuilding site `date`"
if [ $# -eq 1 ]
  then msg="$1"
fi
git commit -m "$msg"

# Push source and build repos.
git push origin source
git subtree push --prefix=public\
	git@github.com:parasquid/parasquid.github.io.git master

It’s a combination of the initial setup and the default deployment script from the Hugo documentation. Now the only downside left (and this is a very minor thing for me) is that post updates can take a few minutes to appear live. But I can live with that.

Also, there will be times when the master branch just won’t deploy because of merge conflicts (and there’s no way to do a force push with git subtree). So far, all I have to do is run deploy.sh one more time, and it’s all cool.

Porting old blog entries to hugo

I’ve blogged on and off for quite some time across various domains and platforms. There really isn’t much I can do to automate importing the entries. Luckily, I only have a handful of published posts, but I probably lost most of my drafts and idea dumps.

Blogging workflow

So now that everything’s set and deployed, how do I continue writing?

Questions?

If any of the instructions above are confusing, feel free to comment, and I’ll try my best to answer your question and update the instructions. :)

Comments

comments powered by Disqus