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.

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 R to work on your website (although that’s less crucial for this gist)
  • 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 R 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.

1. Pull & 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

2. 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 my website .Rproject. If you use R and blogdown for this as well, make sure to test your new website version locally using:


And also make sure to stop the server when you’re happy with your new and improved website:


Clear your \public directory before the last build (which we’ll do in step 3a below) so that no extraneous gunk is left over.

3. Deployment: It’s Git Time

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).

3a. Deploying the Website in \public

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:


# stop deployment if a command fails:
set -e

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

# build the website :
hugo -t academic # if using no theme, remove the `-t academic` bit

# move into public directory:
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 main project (website source docs) to remote:
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 (new commits) for \public, rather than (modified content). At this point, your website is already updated to its newest version; if you navigate to (and cleared your cache), you should see your changes being online.

3b. Adding, Committing, and Pushing our Working Files / 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 same list of changed content as it did before, but as changes to be committed rather than unstaged changes.

Now we commit and push:

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

And we’re done!


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