How to Deploy your Hugo Academic Website on GitHub



Working with git submodules can be tricky, especially for beginner users of git. But, depending on which tutorial you followed to deploy your Hugo website to, Hugo may be using a submodule to deploy the website, and you may need to find a way to work with it.

Maybe this gist can help you if you don’t really know where to start, because God knows I lost a year of my life trying to get this to work when I first switched to GitHub deployment from a “manually FileZilla the public/ folder to my university web space” approach.1

Note that we will be working directly in the master branch; however, feel free to git branch deployTest or the like as you are following along, to merge later (or not, if something goes wrong.)

The following steps assume that you:

  • are using Hugo
  • with the Academic theme
  • have basic command of git and bash, or some sort of Terminal-like application (which I guess you probably do if you are using Hugo for your website and are hosting it on GitHub?)
  • use RStudio and blogdown to work on your website (although that’s less crucial - you could use a code editor/IDE plus HUGO in your terminal for what we’re going to do below. The git deployment process below is agnostic in regards to where your public/ content comes from, or how it was generated.)
  • have a working directory that has your website source documents; in my case, this is called website/
  • in this main project directory, have a public/ folder which houses the actual deployed html files that make up your website, and which is a git submodule to the main project. In my case, the public/ directory is at the same time the submodule to website/.

You may still be able to use this approach if you’re, for example, not using RStudio and blogdown to work on your website, or if you are using a different theme, but you may have to adjust some commands. Or things may not work at all. Who knows. Obviously, YMMV, and test this out first on a directory/repo where you can’t do any harm, and/or which you have securely backed up somewhere else.

Pull and Update from Remote

If you are working on your website from different workstations, this is especially important. Before you start working on anything, update the repo - and, importantly, the submodule - from origin/remote. A regular git pull won’t do here (see for exampe here as to why); instead, run the following in your main project directory (website/, in my case):

	$ git pull --recurse-submodule && git submodule update --recursive

Work on your Website

You can leave git alone for now and work on your website. For me, this means firing up RStudio and working on website.Rproject. If you use RStudio and blogdown for this as well, make sure to test your new website version locally using blogdown::serve_site(), and also make sure to stop the server when you’re happy with your new and improved website by servr::daemon_stop(1).

You may want to clear your public/ directory before creating the final build that you’ll push to GitHub so that no extraneous gunk is left over (better not to mess with hidden files, like .git, however). Below you’ll see that the script that we’ll use will build the site for you, so you don’t need to build the site explicitly before you run the deploy script, although you can of course do that (and blogdown::serve_site() does it automatically anyway if you are using that.)

Deploy Using Git

At this point, git status in the main website directory should show what changes have been made; for example, content/post/, and public (modified content).

Deploy the public/ Folder

We can then go ahead and first deploy the website, meaning: We’ll first push the public/ changes to GitHub. I use a script for this, which I find easier than navigating back and forth, as you can stay in your main project directory the entire time (and it involves less typing and wrestling with submodules and detached HEADs, which can be a headache).

	$ bash

The content of my script look as follows:


# amended by
# on 7 Oct 2019

# If a command fails then the deploy stops
set -e

printf "\033[0;32m Deploying updates to GitHub:\033[0m\n"

# Build the project.
hugo -t academic # if using a theme, replace with `hugo -t <YOURTHEME>`

# Go To Public folder
cd public

printf "\033[0;32m Now in /public folder.\033[0m\n"

# Add changes to git.
printf "\033[0;32mChecking out master branch.\033[0m\n"
git checkout master
printf "\033[0;32mStaging changes.\033[0m\n"
git add .

# Commit changes.
printf "\033[0;32mCommitting.\033[0m\n"
msg="rebuilding site $(date)"
if [ -n "$*" ]; then
git commit -m "$msg"

# Push source and build repos.
printf "\033[0;32mPushing to GitHub.\033[0m\n"
git push origin master

… which really is just a slightly more verbose version of the script you’ll find on Hugo’s Host on GitHub page. Also see Academic’s Deployment page in this context.

Calling git status (still in our main website/ folder - we’re not leaving it at any point during this process) now shows changed source files, and (new commits) for public/:

On branch master
Your branch is up to date with 'origin/master'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   content/post/20191007-hugo-deploy/
	modified:   public (new commits)

no changes added to commit (use "git add" and/or "git commit -a")

Add, Commit, and Push Source Docs

Now all that’s left to do is to push the changes in our working files (i.e. the main project / website/ folder) to GitHub. However, you will notice in git status that the modified stuff is not staged for commit yet. We’ll do that now (use the dot after git add only if you are sure from looking at your list of modified content that it’s all good to go - otherwise refer to each file individually):

	$ git add .

$ git status should now show the changed content as changes to be committed rather than unstaged changes, like so:

On branch master
Your branch is up to date with 'origin/master'.

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	modified:   content/post/20191007-hugo-deploy/
	modified:   public

Now we commit and push:

	$ git commit -m "your message here"
	$ git push

And we’re done! You can use git status to check that everything is up to date.


The following helped me immensely in my quest to find a smooth approach to deploying using submodules:


1] The agony of constantly having to remember which of my workstations and/or USB drives had the most current version of my website, which my brain somehow wasn’t able to manage, was the main push for the move to GitHub. So far, I have had no regrets.

Isabell Hubert Lyall
Post-Doctoral Fellow & Assistant Lecturer

Post-Doctoral Fellow at the Centre for Comparative Psycholinguistics at the University of Alberta, working with Dr. Juhani Järvikivi. Also Assistant Lecturer at the University of Alberta teaching LING 101, & Vice-Chair of the Edmonton Transit Service Advisory Board (ETSAB).