How to Publish a Hugo Site on Netlify With a Private Theme

May 26, 2018

Git submodules are the documented way to use Hugo themes with Netlify. Unfortunately, they do not work with private themes.

Netlify deploys fail with an error like fatal: could not read Password for ...: No such device or address or fatal: could not read Username for ...: No such device or address.

But why?

The Solution: Git Subtree

You can find a hint to a solution in the Netlify blog post How Our Build Bots Build Sites:

If you have submodules that are in private repositories, or private node modules, or other git repositories that you need separate access to - well, our build environment only has access to them in case you send the authentication raw materials our way somehow. In general we don’t advise this - for instance: use subtrees instead of submodules and create a copy of the private node modules before sending us a deploy.

So, git subtrees allow to publish Hugo sites with private themes on Netlify.

How to do it?

You can copy a public theme into a private repository and then add the private repository as git subtree to your site.

The big picture looks like this:

To start, create a new repository.

Then, copy the public theme repository into the new repository with the commands git clone --bare and git push --mirror.

Next, create a git subtree within your site with git subtree add. Whenever you now git push your site, the subtree content will be included and Netlify can deploy it.

To push changes back to your private theme repository, use the command git subtree push.

A Step-By-Step Guide

Here is a step by step guide. We will create a custom theme called mycapsule based on the Capsule theme and use it in a Hugo site called mysite. I used my Bitbucket account while creating this example. Please change the repository URL accordingly.

# change repo url accordingly
export REPO_URL=

1. Create a new repo via the Github, Gitlab or Bitbucket UI.

This is how it looks on Bitbucket:

2. Make a copy of the upstream theme and push it into your newly created repository.

git clone --bare
cd capsule.git
git push --mirror $REPO_URL
cd ..
rm -rf capsule.git

3. Add your private theme as a subtree to your Hugo site:

cd mysite
git subtree add --prefix themes/mycapsule --squash $REPO_URL master
# now change the theme in config.toml to theme = "mycapsule"
git add .
git commit -m "use mycapsule theme via a git subtree"
git push

4. Push changes back to your theme repository.

The changes are now pushed to your hugo site repository. To push your theme changes to your theme repository as well, use the command git subtree push. The use of git remote is optional but nice as it simplifies the push command.

git remote add mycapsule $REPO_URL
git subtree push --prefix=themes/mycapsule mycapsule master

Merging in changes from the upstream public theme repository.

You can use a separate working copy for your theme to merge in changes from upstream. To do so, clone your private repository into a separate working directory. Then, add the upstream theme repository as a remote. Finally, pull from upstream and push the merge into your private repository:

git clone $REPO_URL
cd mycapsule
git remote add upstream
git pull upstream master # creates a merge commit
git push origin master

Conclusion and Credits

This is a bit complicated at first but simple to use day to day. After the initial setup, the theme can be changed and pushed to the Hugo site repository without worrying about submodules or subtrees.

Even if you just go with a public theme you should probably still first make a copy of it. Having a copy right from the start is easier than Moving a Git Subtree to Its Own Repository later on.

Two sources have been helpful: