The last time I dabbled in the background for this Hugo-powered site, I was deploying it to a webserver I pay for. Since then, I’ve been looking at how to deploy it to GitHub Pages for free, and to simplify a multiple-workstation-life.

The caveat to GitHub Pages is that, on a free GitHub account, you can only use the feature on public repositories. What I wanted to do was keep my source files and drafts in a private repository, and have the generated static site pushed to the public repository which GitHub Pages would pull from.

This is how I managed it using git submodule. A word of warning: submodules are complicated. This setup works well for me, a singular person, who updates on one machine. Nonetheless, I hope this post helps someone as a starting point.

Note: If you really do not want it to be a public repository, Netlify allows deploys in private repositories!

Setting up submodules

I have two GitHub repositories:

  • <username> is the public, GitHub pages-enabled repository
  • blog is the private repository holding source files and all drafts

In Hugo, the hugo command generates the static site in a /public directory by default. So /public has to be move from being a directory in the blog private repository to its own public repository pointing to <username>

I used Git submodules for this. It’s confusing. So here is what worked for me.

First, I deleted the public folder (rm -rf public). This is okay because we can generate those files again. Then:

git submodule add<username>/<username> public
git submodule init

The first line checks out the GitHub Page repository and adds it to the blog repository under the directory public.

The second line pulls the code from the repository.

For sanity check, I hugo to generate files to the public directory. I cd public and check git remote -v and then cd .. and check git remote -v to make sure they’re pointing to different repositories.

If, like me, you managed to mess up your submodules, checking what was up in the /.git/modules directory helped me to clean up.

A new deploy script

All right, so now the commands to deploy are a little finicky. I have to generate the site, push the changes to the public repository, then push the source files to the private repository. Not only that, Hugo changes and adds files, it doesn’t delete. So I have to wipe the contents of public without removing its references to Git. Whew.

So I ended up with an executable (chmod +x script like this:

rm -rf public/* # Remove all files except dot files
# echo "<domain.tld>" >> public/CNAME # If you use a custom domain

hugo # Generate the static files into /public

cd public 
git add .
git commit -m "Rebuilding site"
git push origin master

cd ..
git add .
git commit -m "Updating source and draft content"
git push origin master

Now, once you create your content, you can use ./ and it will generate the new files, and add it to each respective Git repository. It is not quite clean — if you are using multiple machines, you will need to git submodule init and then git submodule update to set the remotes correctly.