As I wrote in my first post here, I wanted to use version control for this website. Version control is a software development management tool that gives separate layers–in this case, I can be working on a new feature or design and not have it appear on the website until I’m ready. It also lets me undo things and change course easily.
I chose to use Git mainly because it’s pretty standard but also to give me a chance to learn it in a real-world environment.
Years from now, I don’t want to have to know what version of Hugo to use to regenerate an old website if needed. So I actually have two Git repositories for this site:
- Source, the raw data Hugo uses to generate the website.
- Public, the complete website you’re reading right now.
Writing for the website is pretty simple.
- I’ve cloned the source repo onto my daily-use Mac. When I’m ready to write something new, I run
hugo new blog/title.mdthen edit the file that’s created.
- When I’m ready to test, I’ll run
hugo server -Dw. Hugo will watch the files and rebuild the test site if there are changes. I can check to see how the new post will appear using a web browser.
- Once I’m happy with it, I commit the changes:
git commit, and
But remember, this is only the source used by Hugo to make the website. (Since I want to separate the two repositories, I added the
public/ directory Hugo uses to store the test files to the
How to Automatically Deploy
The key part in making the updated website visible on the Internet is the last part of step three:
git push. On the server, I run a Git hook located under
#!/bin/bash GIT_REPO=$HOME/website-source.git TMP_GIT_CLONE=$HOME/tmp/website-source PUBLIC_WWW=/srv/www # Wait up to 2 seconds for the STDIN to get here. read -t 2 from_commit to_commit branch_name # Only deploy if the master branch was pushed. Full variable is similar to "refs/heads/master". if [[ "$branch_name" != */master ]]; then echo "Received branch $branch_name, not deploying." exit 1; fi # Make temporary clone for site generation. git clone $GIT_REPO $TMP_GIT_CLONE # Run hugo using config in repo, no draft or future content will be created. cd $TMP_GIT_CLONE hugo # Copy files to www server root. Some files are excluded so they don't overwrite or delete # required files in the server root. rsync -rvh --delete --exclude='.git/' --exclude='.gitignore' $TMP_GIT_CLONE/public/ $PUBLIC_WWW/ # We're done, so clean up. rm -rf $TMP_GIT_CLONE
When I push the updates from my Mac, the server runs this script and I don’t have to run each command manually!
Some sections that might require more explanation are:
- Line 10: Check if the master branch was pushed. I don’t need to regenerate the website if I’m working on a feature branch that isn’t live yet.
- Line 20: Run
hugo. I don’t need any parameters here because my
config.tomlfile for Hugo lists the theme to use, etc.
- Line 24: The
rsynccommand line options.
--deletemakes sure there aren’t any orphaned files on the public site. Basically, if I remove a file in the source, that change carries over.
--exclude='.git/' --exclude='.gitignore'leaves the special Git files in the public directory alone. This means I can easily maintain the second Git repository I mentioned near the beginning. (That public repository is managed manually.)
If you do something similar, make sure to run the same Hugo version on your local and server computers. That way, the site built for local testing will be the same as the one generated on the server.