Hugo Themes - Making Modifications while Keeping the Source Up-To-Date
Tags: hugo, jamstack, githubpages, submodules
Published: 2020-09-30 00:35:46

---
title: Hugo Themes - Making Modifications while Keeping the Source Up-To-Date
published: true
date: 2020-05-19 18:30:00 UTC
tags: [hugo, jamstack, githubpages, submodules]

cover_image: https://www.adamormsby.com/posts/000/hugo-themes-making-modifications/cover.jpg

description: "In today's post, I want to take a look at how we can keep our Hugo themes up-to-date. The key to this process is using git submodules to track and pull updates to a theme with just a few quick commands."

canonical_url: https://www.adamormsby.com/posts/hugo-themes-making-modifications/

series: Build Static Websites with Hugo
---

 ![](https://www.adamormsby.com/posts/hugo-themes-making-modifications/cover.jpg)

## Overview

In today’s post, I want to take a look at how we can keep our Hugo themes up-to-date. ‘But my theme works fine!’ you say. ‘Why would I ever need to update it?’ Well, when you download or clone a Hugo theme from its hosted git repository, you’re getting its latest version _at that point in time._ So even if the theme’s creator pushes updates to the code - with fixes, new features, and outside pull requests - you’ll still be stuck using the version you downloaded before. While this is fine in some cases, many of us want the newest updates so we can take advantage of a stronger, improved theme.

The key to this process is using git submodules to track and pull updates to a theme with just a few quick commands. If you followed my previous tutorial on [adding a theme to your Hugo site as a git submodule](https://dev.to/aormsby/how-to-set-up-a-hugo-site-on-github-pages-with-git-submodules-pbc-temp-slug-1243121), you already have a functional Hugo site with a (forked) theme included. Starting there, let’s see how to connect our theme to its remote source repo, which git commands we need to update it, and even how to safely make our own custom changes to the theme while keeping it in line with the source.

## Just the Updates, Please

If we don’t intend to customize a theme at all, we can keep our workflow super simple. All we need to do is add the theme repo into our project as a submodule and periodically run a few git commands to check for updates. For the moment, let’s pretend we haven’t forked the theme repo and see what it would be like to clone the source directly. We’ll see an example with our fork in the next section.

Here’s a quick refresher command for adding a submodule to our project.

```
> git submodule add https://github.com/panr/hugo-theme-hello-friend.git themes/hello-friend

```

> You might be thinking you can simply run `git clone` instead of adding the theme as a submodule, but our site is already set up as a git repo so that doesn’t work here. Git doesn’t like having `.git` files in a subdirectory without a `.gitmodules` component in the root. For more on that, see [this ‘simple dev’ post.](https://wespeter.com/posts/avoiding-git-problems-when-installing-a-theme-to-hugo/)

In the example above, we added our submodule by pulling the theme’s source repo directly into our project. With the `git remote` command, we can easily verify that it’s connected to the correct remote repo.

```
> cd themes/hello-friend
> git remote --verbose
origin https://github.com/panr/hugo-theme-hello-friend.git (fetch)
origin https://github.com/panr/hugo-theme-hello-friend.git (push)

```

 ![one-way update directly from theme source](https://www.adamormsby.com/posts/hugo-themes-making-modifications/img/simple-update.jpg)

And there it is! With this setup, all we need to do is pull updates straight from the source. From the theme’s directory, we run the following terminal commands.

```
# optional: fetch any updates to view changes before merging
> git fetch origin
> git status
[status output here]

# pull updates and merge them automatically
> git pull

```

Since we’re not making any theme changes in this workflow, we shouldn’t expect any merging issues during the `git pull`. We don’t really _need_ to fetch or check the status of the repo, but it’s always nice to see incoming changes before we bring them in.

And that’s it! Getting updates every so often is no problem if we don’t intend to make our own customizations to a theme. But hey - customization is where the fun _really_ begins.

## Updates and Theme Customization - A Parallel Branch Workflow

Here’s the scenario - We want to add a Hugo theme, make custom changes, and still to get updates from the theme’s original source. The method used above doesn’t work here for a few reasons:

1. **We can’t push our custom changes to the theme’s source repo**. We simply don’t have those permissions on the repo. Our local changes will not be safely stored anywhere, and any pulled updates may not be easily mergeable.
2. **Incoming updates may require merges.** If we’ve modified some of the theme files that are being updated in the source, then a simple `git pull` will not be enough to deal with the resulting conflicts.

Thankfully, a more advanced git workflow would help deal with these issues. Remember [how we set up a forked theme repo](https://www.adamormsby.com/posts/how-to-set-up-a-hugo-site-on-github-pages-with-submodules/#add-a-theme-to-our-site) in the last post? Now we get to take advantage of it. Crucially, the forked repo is _ours_, so we have full write access to it and don’t need to worry about repo permissions. We can do whatever we want.

### Add a Remote Repo

However, our fork doesn’t automatically receive source updates either! Here, an additional step is needed to link our fork back to the source repo. Earlier, in the direct update workflow, we used the `git remote` command to verify that we had the correct remote repo connections. Running it in our forked theme directory, we see only the fork as our remote.

```
# my forked repo URLs as an example
> git remote --verbose
origin https://github.com/aormsby/F-hugo-theme-hello-friend.git (fetch)
origin https://github.com/aormsby/F-hugo-theme-hello-friend.git (push)

```

To get updates from the source repo, we need to add a _second_ remote repo - yes, git can do this! We simply run this command in our working directory and check our remotes again to verify the connection.

```
# add a new remote repo connection
> git remote add upstream https://github.com/panr/hugo-theme-hello-friend.git

> git remote --verbose
origin https://github.com/aormsby/F-hugo-theme-hello-friend.git (fetch)
origin https://github.com/aormsby/F-hugo-theme-hello-friend.git (push)
upstream https://github.com/panr/hugo-theme-hello-friend.git (fetch)
upstream https://github.com/panr/hugo-theme-hello-friend.git (push)

```

Ta-da! Our local theme repo is now linked to both our forked repo _and_ the source repo, which we called `upstream`. (This is a conventional label, but any name you choose is fine.) At this point, our setup already supports getting updates from the source, but the process is a little different than before.

Normally, when we’re updating directly from a single remote repo, all we need to do is `pull` the data to our local directory so that the local matches the remote. We’ll still do that here, but we explicitly pull data from the `upstream` repo we added. We’ll also have to make an additional `push` to our forked repo - `origin` - to update it with the new code. Here’s how that works compared to the previous example.

![comparison of update methods](https://www.adamormsby.com/posts/hugo-themes-making-modifications/img/forked-update.jpg)<figcaption>Left: simple update / Right: updating with a fork</figcaption>

Assuming you’re still on your `master` branch, here are the modified commands needed to pull and push the updates.

```
# optional: fetch any updates to view changes before merging
> git fetch upstream master
> git status
[status output here]

# pull updates and merge them automatically
> git pull upstream master

# push source updates to forked repo
> git push origin master

```

With no local changes to our theme, the commands run smoothly with no errors - and we want to keep it that way! Simple is good, and an update process that doesn’t result in merge conflicts is always nice. But how do we manage to avoid conflicts if we want to customize the theme? Simple - don’t do your work on `master`.

### Branching, Customizing, and Merging Updates

Although you technically _could_ make theme customizations on the `master` branch, this increases the chances of having to resolve merge conflicts every time you try to pull an update. It’s fine if that’s how you want to work, but I _highly_ recommend avoiding it. In my experience, it’s often best to keep `master` sparkly clean and do your dirty work on a different branch.

For example, I do my theme in a separate branch that is always kept in parallel with `master`. I’ve named it `working`, as it’s the branch that I _work_ in. (Not exactly clever, I know.) Since it has all of my theme customizations, it’s also the branch that I use when I build my site. Every so often, I switch back over to `master`, go through our update process, and then explicitly merge any new theme updates from `master` into `working` so that I have all the latest features in my working branch. Visually, it’s kind of like this.

 ![parallel branch system with updates merged from master](https://www.adamormsby.com/posts/hugo-themes-making-modifications/img/parallel-branches.jpg)

This is just one possible theme customization workflow, but we can benefit from a setup like this. For example –

- **Our workspace is separate from our update environment.** Getting theme updates will always be a painless process, and we have more control over merging when the time comes.
- **Commit histories are clearer.** Histories are much easier to read if source updates and custom work don’t get tangled up, and this can be super helpful when performing more advanced git actions on a branch.
- **All the data is on our forked repo.** The customizations _and_ the pulled updates all live on our fork, which means we have full control of the data.
- **We can test on `master` before merging.** If we’re unsure of how a new feature will display on our site, we can run a build using the `master` code. It’s a nice clean test bed before performing a merge.

The drawbacks are much the same as I mentioned in the [last post](https://www.adamormsby.com/posts/how-to-set-up-a-hugo-site-on-github-pages-with-submodules/#some-drawbacks) with the addition that now we’d have at least one more working branch to manage. However, I’ve found this parallel branch workflow quite nice after getting more familiar with it. Perhaps you will, too.

Here are the commands we can use to get our `working` branch up and running. (You can choose a better name if you’d like.)

```
# create a new branch and switch to it
> git branch working
> git checkout working

```

We make some changes, commit our work, and push to our forked repo ([see these commands for help](https://www.adamormsby.com/posts/how-to-set-up-a-hugo-site-on-github-pages-with-submodules/#test-site-and-deploy)). Time passes… and we want to get some updates on `master`.

```
# switch to master branch
> git checkout master

# quick update
> git pull upstream master
> git push origin master

```

Finally, we switch back to `working` and merge in the updates from `master`.

```
# switch to working
> git checkout working

# merge master into current branch (working)
> git merge master

```

I won’t get into resolving a merge here, so let’s cross our fingers and hope there are no conflicts to deal with.

![git merge conflict comic](https://www.adamormsby.com/posts/hugo-themes-making-modifications/img/git-merge-conflict.jpg)<figcaption>something to look forward to :)</figcaption>

So yes - customizing your theme with this kind of workflow does take a bit of setup, and there are a few extra steps and things to keep track of to manage our code well. However, using git submodules and a parallel branch workflow do give us more leverage over our codebase, and I think that makes the extra work worthwhile. I’ve been using this workflow with my site for some time, and I don’t think I’d change anything about it.

That said, there are a number of other methods that people use for managing their themes, and it’s worth exploring them to see what fits your needs best. I recently read a post about [managing your themes as Hugo modules by Nick Gracilla](https://www.hugofordevelopers.com/articles/master-hugo-modules-managing-themes-as-modules/) that I found quite interesting, and I think it’s worth checking out if you’re looking for an alternate way of doing things.

## Next Steps

- [Better Deploy](https://www.adamormsby.com/posts/hugo-shell-deploy-script/) - I’m still working on a better site deploy script! It’s looking good so far, but it’s not quite ready.
- **Automatic Builds** - This would still be great to have, so if I get around to it I’ll be sure to share my work.

Until next time! ~