How to Deploy a Hugo Website via GitHub Pages

Hongtao Hao / 2020-11-29

2021-04-06: As of April 06, 2021, Hugo only recommends deployment with GitHub Action .

GitHub Action is superior to the method mentioned below because (1) You don’t need to run hugo to build your site locally; (2) It is easier to leave a custom commit message. The method below necessitates a script, which makes a custom message difficult.

Read How to Deploy A Hugo Website Using GitHub Pages Action for instructions on deploying your site with GitHub Action.


I had a nightmare yesterday: I messed up the automatic deployment process of my Hugo website. My initial deployment process was based on this tutorial post by Jente Hidskes . Although it was a little bit outdated and complicated, it served me well. That was until yesterday.

What happened was that I deleted some images from the static folder. What I should have done is simply to run bash to regenerate and update the site. However, I wanted to leave a commit message to myself, so I ran in Terminal git add . & git commit -m "deleting images." & git push origin master. The thing is, I probably should have used git push origin sources since the sources branch holds my original repository whereas the master branch is in fact the public folder.

I messed it up. Since the original codes for the deployment were very complicated, I wasn’t able to fix it myself. I tried so many methods, but they all failed.

So I had to give up and try to deploy it anew.

There are many ways to deploy a Hugo website. The simplest one perhaps is to host it on Netlify . However, my site deployed by Netlify looks a little bit different from what I see on my local server. So I had to give it up.

I chose to use GitHub Pages. Hugo’s homepage detailed three ways to host a Hugo website though GitHub Pages. The first method is to set up two repositories with one being the submodule. I don’t like the idea of managing two repositories for my website, so I didn’t choose it. The second option , perhaps the easiest one, is to change the publish directory from public to docs, so that GitHub Pages can automatically recognize that the site to deploy is located in the folder of /docs. However, I didn’t like the idea of changing the default publish directory either (Yeah, call me picky if you want).

I chose the third option , which is to set up a new branch called gh-pages which is essentially the public folder. I will document the steps I took to restore my site’s deployment, in case I need to redo it. It may also help others.

Restore the content #

Since I messed it up, I decided to delete all the content. After having deleted everything manually in the root directory, I ran these:

git add .
git commit -m "Deleting everything."
git push origin <master-branch>

The name of my <master-branch> is sources, so I’ll use sources in the following parts.

Then, find out the <commit ID> I want to restore. That should be the one before I messed up everything. Run

git checkout <commit ID> .

As this tutorial said, do not forget the dot after <commit ID>. Also, there is space before the dot.

After that, delete public before pushing everything to sources: rm -rf public. This is because I don’t need public now and if I include it, it will take more time when pushing.

Then, push the restored content to <master branch> branch:

git add .
git commit -m "Restoring."
git push origin sources

Set up gh-pages #

First, delete all the .DS_Store files:

find . -name .DS_Store -print0 | xargs -0 git rm -f --ignore-unmatch
git add .
git commit -m "Remove .DS_Store from everywhere"
git push origin sources

The following steps are based on the official tutorial . I modified it a little bit.

Then, edit .gitignore:

echo "public" >> .gitignore
echo ".DS_Store" >> .gitignore

If you want to edit .gitignore manually, you can use open .gitignore -a TextEdit or open .gitignore -a "Sublime Text".

Then, build and deploy:

rm -rf public
git worktree add -B gh-pages public origin/gh-pages

Regenerate the site and commit the public folder to gh-pages:

cd public && git add --all && git commit -m "Publishing to gh-pages" && cd ..
git push origin gh-pages

On GitHub, go to Settings → GitHub Pages, then choose “gh-pages”. The site should be running.

Automatic deployment #

The script file provided is a little bit weird, especially the if statement. If it is there, and I added some content to the root directory, then I cannot deploy.

Also, the guidance of Use a Custom Domain provided is a little bit confusing. If I add the CNAME file to the static folder, something will go wrong.

The following script is what I came up with, based on the original one :

MESSAGE="Rebuilding site $(date)"
git add .
git commit -m "$MESSAGE"
git push origin "$SOURCE"

if [ "`git status -s`" ]
    echo "The working directory is dirty. Please commit any pending changes."
    exit 1;

echo "Deleting old publication"
rm -rf public
mkdir public
git worktree prune
rm -rf .git/worktrees/public/

echo "Checking out gh-pages branch into public"
git worktree add -B gh-pages public origin/gh-pages

echo "Removing existing files"
rm -rf public/*

echo "Generating site"

cd public
echo "" > CNAME

echo "Updating gh-pages branch"
git add . && git commit -m "Publishing to gh-pages ("

echo "Pushing to github"
git push --all origin

Last modified on 2021-10-05