mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-07 20:30:36 -05:00
docs: Update tutorial on GitHub Pages deployment
Now it describes the deployment via /docs folder and git worktree.
This commit is contained in:
parent
85c7578313
commit
3818d6967a
1 changed files with 94 additions and 190 deletions
|
@ -1,8 +1,8 @@
|
|||
---
|
||||
aliases:
|
||||
- /tutorials/github_pages_blog/
|
||||
author: Spencer Lyon
|
||||
lastmod: 2016-01-14
|
||||
author: Spencer Lyon, Gunnar Morling
|
||||
lastmod: 2017-01-11
|
||||
date: 2014-03-21
|
||||
linktitle: Hosting on GitHub
|
||||
toc: true
|
||||
|
@ -15,229 +15,126 @@ title: Hosting on GitHub Pages
|
|||
weight: 10
|
||||
---
|
||||
|
||||
> *This tutorial was contributed by [Spencer Lyon](http://sglyon.com/).*
|
||||
*This tutorial was contributed by [Spencer Lyon](http://sglyon.com/) (Personal/Organization Pages) and [Gunnar Morling](https://github.com/gunnarmorling/).*
|
||||
|
||||
## Introduction
|
||||
|
||||
Many Hugo users have expressed interest in seeing a tutorial for how to set up a blog that is generated by Hugo and hosted on GitHub Pages. This tutorial will do just that. We only require that the reader has Hugo installed correctly and is comfortable with git and GitHub.
|
||||
This tutorial describes how to deploy your Hugo based website to [GitHub pages](https://pages.github.com/).
|
||||
|
||||
During this tutorial, I will walk you through the main steps I took to create an example blog available at [http://spencerlyon2.github.io/hugo_gh_blog](http://spencerlyon2.github.io/hugo_gh_blog). The source code for this blog is on [GitHub](https://github.com/spencerlyon2/hugo_gh_blog). Readers are encouraged to download the example repository and follow along.
|
||||
The following sections are based on the assumption that you are working with a "Project Pages Site".
|
||||
This means that you'll have your Hugo sources and the generated HTML output within a single repository
|
||||
(in contrast, with a "User/Organization Pages Site", you'd have one repo for the sources and another repo for the published HTML files;
|
||||
refer to the [GitHub Pages docs](https://help.github.com/articles/user-organization-and-project-pages/) to learn more).
|
||||
|
||||
### Find a Home for Your Files
|
||||
## Deployment via _/docs_ folder on master branch
|
||||
|
||||
As our goal is to host a website using GitHub Pages, it is natural for us to host the content of the page in a GitHub repository. Thus, the first step is to either create a new repository on GitHub or create a new directory within an existing repository where the content of the website will live. To do this, I created the repository [spencerlyon2/hugo_gh_blog](https://github.com/spencerlyon2/hugo_gh_blog).
|
||||
[As described](https://help.github.com/articles/configuring-a-publishing-source-for-github-pages/#publishing-your-github-pages-site-from-a-docs-folder-on-your-master-branch) in the GitHub Pages docs, you can deploy from a folder called _docs_ on your master branch.
|
||||
This requires to change the Hugo publish directory in the site config (e.g. _config.toml_):
|
||||
|
||||
## Create the Blog
|
||||
publishDir: "docs"
|
||||
|
||||
### Write a `config.yaml` File
|
||||
After running `hugo`, push your master branch to the remote repo and choose the _docs_ folder as the website source of your repo
|
||||
(in your GitHub project, go to "Settings " -> "GitHub Pages" -> "Source" -> Select "master branch /docs folder").
|
||||
If that option isn't enabled, you likely haven't pushed your _docs_ folder yet.
|
||||
|
||||
The very first step in creating a new Hugo site is to [write the config file](/overview/configuration/). This config file is important for at least two reasons: (1) this is where site-wide settings (like the websites `baseURL`) go, and (2) the config file dictates to some extent how Hugo will generate the website. For the example website I created a file `config.yaml` with the following contents
|
||||
This is the simplest approach but requires the usage of a non-standard publish directory
|
||||
(GitHub Pages cannot be configured to use another directory than _docs_ currently).
|
||||
Also the presence of generated files on the master branch may not be to eveyone's taste.
|
||||
|
||||
---
|
||||
contentDir: "content"
|
||||
layoutDir: "layouts"
|
||||
publishDir: "public"
|
||||
indexes:
|
||||
category: "categories"
|
||||
baseURL: "http://spencerlyon2.github.io/hugo_gh_blog"
|
||||
title: "Hugo Blog Template for GitHub Pages"
|
||||
canonifyURLs: true
|
||||
...
|
||||
## Deployment via gh-pages branch
|
||||
|
||||
> **Caveat:** Hugo's former default of `canonifyURLs: true` has been changed
|
||||
> to `false` since this tutorial has written. **Please make sure you manually
|
||||
> add `canonifyURLs: true` to your `config.yaml`** if you are using Spencer's
|
||||
> https://github.com/spencerlyon2/hugo_gh_blog for this tutorial, or you *will*
|
||||
> run into problems such as the CSS files not loading.
|
||||
Alternatively, you can deploy site through a separate branch called "gh_pages".
|
||||
That approach is a bit more complex but has some advantages:
|
||||
|
||||
> See ["Canonicalization: Caveat" on the "Extras: URLs page"](/extras/urls/)
|
||||
> for more information.
|
||||
* It keeps sources and generated HTML in two different branches
|
||||
* It uses the default _public_ folder
|
||||
* It keeps the histories of source branch and gh-pages branch fully separated from each other
|
||||
|
||||
### Define Structure of Website
|
||||
### Preparations
|
||||
|
||||
Hugo assumes that you organize the content of your site in a meaningful way and uses the same structure to render the website. Notice that we have the line `contentDir: "content"` in our configuration file. This means that all the actual content of the website should be placed somewhere within a folder named `content`. Hugo treats all directories in `content` as sections. For our example we only need one section: a place to hold our blog posts. So we created two new folders:
|
||||
These steps only need to be done once (replace "upstream" with the name of your remote, e.g. "origin"):
|
||||
First, add the _public_ folder to _.gitignore_ so it's ignored on the master branch:
|
||||
|
||||
```
|
||||
▾ <root>/
|
||||
▾ content/
|
||||
▾ posts/
|
||||
```
|
||||
echo "public" >> .gitignore
|
||||
|
||||
### Create HTML Templates
|
||||
Then initialize the gh-pages branch as an empty [orphan branch](https://git-scm.com/docs/git-checkout/#git-checkout---orphanltnewbranchgt):
|
||||
|
||||
The next step is to define the look and feel of your new website. Because Hugo will generate the site using HTML templates written by the user (you), this step is very subjective. I will merely present one possible theme that could be used to generate a blog. I decided to base the example project on a Jekyll theme called [Lanyon](http://lanyon.getpoole.com/). The Lanyon theme is pure CSS and a slightly modified version of the CSS is in the `/static/css` directory of the example repository. If you are following along, you should grab the `static` folder from the example repository and put it alongside the `content` folder you just created.
|
||||
|
||||
Because there are so many files needed to fully compose a complete website, I will not be able to go through each of them here. I will, however, show what the directory structure should look like when all is said and done:
|
||||
|
||||
```
|
||||
▾ <root>/
|
||||
▾ content/
|
||||
▾ posts/
|
||||
<blog posts>.md
|
||||
▾ static/
|
||||
▾ css/
|
||||
lanyon.css
|
||||
poole.css
|
||||
▾ layouts/
|
||||
▾ partials/
|
||||
<templates to be used in other files>.html
|
||||
▾ posts/
|
||||
li.html
|
||||
single.html
|
||||
summary.html
|
||||
▾ indexes/
|
||||
category.html
|
||||
indexes.html
|
||||
posts.html
|
||||
index.html
|
||||
README.md
|
||||
```
|
||||
|
||||
Each of the files in the example repository is well commented with a description of what the file as a whole does as well as an explanation of all major components in the file. If you are new to web development and/or Hugo, I encourage you to search through these files to get a feel for how Hugo templates work and how the site is stitched together.
|
||||
|
||||
### Add Some Content
|
||||
|
||||
The final step in creating the blog is to add some actual blog posts. To do this, simply create one Markdown file (with extension `.md`) for each new blog post. At the top of each file you should include a metadata section that tells Hugo some things about the post (see [docs](/content/front-matter/)). For example, consider the yaml metadata section from the top of the file `/content/posts/newest.md` from the example repository:
|
||||
|
||||
---
|
||||
title: "Just another sample post"
|
||||
date: "2014-03-29"
|
||||
description: "This should be a more useful description"
|
||||
categories:
|
||||
- "hugo"
|
||||
- "fun"
|
||||
- "test"
|
||||
---
|
||||
|
||||
The keys set in this section are the mandatory `title` and `date` as well as the optional `description` and `categories`. Each of these items is used throughout the templates found in the `/layouts` directory and gives Hugo information about the post from other pages in the website.
|
||||
|
||||
## Configure `git` Workflow
|
||||
|
||||
Once the site is set up and working properly, we need to push it to the correct branch of a GitHub repository so the website can be served through GitHub Pages. There are many ways to do this. Here I will show the workflow I currently use to manage my websites that are hosted through GitHub Pages.
|
||||
|
||||
GitHub Pages will serve up a website for any repository that has a branch called `gh-pages` with a valid `index.html` file at that branch's root. A typical workflow might be to keep the content of a website on the `master` branch of a repository and the generated website on the `gh-pages` branch. This provides nice separation between input and output, but can be very tedious to work with. As a workaround, we will use the `git subtree` family of commands to have the `public` directory (or whatever `publishDir` is set to in your `config.yaml`) mirror the root of the `gh-pages` branch of the repository. This will allow us to do all our work on the `master` branch, run Hugo to have the site output into the `public` directory, and then push that directory directly to the correct place for GitHub Pages to serve our site.
|
||||
|
||||
To get this properly set up, we will execute a series of commands at the terminal. I will include all of them in one place here for easy copy and paste, and will explain what each line does via comments. Note that this is to be run from the `<root>` directory (wherever the `content` and `layout` folders of your Hugo project live). Also note that you will need to change the commands that have the example repository GitHub address so that they point to your repo.
|
||||
|
||||
# Create a new orphand branch (no commit history) named gh-pages
|
||||
git checkout --orphan gh-pages
|
||||
|
||||
# Unstage all files
|
||||
git rm --cached $(git ls-files)
|
||||
|
||||
# Grab one file from the master branch so we can make a commit
|
||||
git checkout master README.md
|
||||
|
||||
# Add and commit that file
|
||||
git add .
|
||||
git commit -m "INIT: initial commit on gh-pages branch"
|
||||
|
||||
# Push to remote gh-pages branch
|
||||
git push origin gh-pages
|
||||
|
||||
# Return to master branch
|
||||
git reset --hard
|
||||
git commit --allow-empty -m "Initializing gh-pages branch"
|
||||
git push upstream gh-pages
|
||||
git checkout master
|
||||
|
||||
# Remove the public folder to make room for the gh-pages subtree
|
||||
### Building and Deployment
|
||||
|
||||
Now check out the gh-pages branch into your _public_ folder, using git's [worktree feature](https://git-scm.com/docs/git-worktree)
|
||||
(essentially, it allows you to have multiple branches of the same local repo to be checked out in different directories):
|
||||
|
||||
rm -rf public
|
||||
git worktree add -B gh-pages public upstream/gh-pages
|
||||
|
||||
# Add the gh-pages branch of the repository. It will look like a folder named public
|
||||
git subtree add --prefix=public git@github.com:spencerlyon2/hugo_gh_blog.git gh-pages --squash
|
||||
Regenerate the site using Hugo and commit the generated files on the gh-pages branch:
|
||||
|
||||
# Pull down the file we just committed. This helps avoid merge conflicts
|
||||
git subtree pull --prefix=public git@github.com:spencerlyon2/hugo_gh_blog.git gh-pages
|
||||
|
||||
# Run hugo. Generated site will be placed in public directory (or omit -t ThemeName if you're not using a theme)
|
||||
hugo -t ThemeName
|
||||
|
||||
|
||||
# Add everything
|
||||
git add -A
|
||||
|
||||
# Commit and push to master
|
||||
git commit -m "Updating site" && git push origin master
|
||||
|
||||
# Push the public subtree to the gh-pages branch
|
||||
git subtree push --prefix=public git@github.com:spencerlyon2/hugo_gh_blog.git gh-pages
|
||||
|
||||
After executing these commands and waiting for the GitHub servers to update, the website we just created was live at [http://spencerlyon2.github.io/hugo_gh_blog](http://spencerlyon2.github.io/hugo_gh_blog).
|
||||
|
||||
### `deploy.sh`
|
||||
|
||||
Now, as you add new posts to your blog, you will follow steps that look something like the following:
|
||||
|
||||
* Create the Markdown source for the new post within the `content/posts` directory
|
||||
* Preview your work by running Hugo in server mode with `hugo server`
|
||||
* Run Hugo not in server mode so that the generated urls will be correct for the website
|
||||
* Add and commit the new post in `master` branch
|
||||
* Push the `master` branch
|
||||
* Push the public subtree to the remote `gh-pages` branch
|
||||
|
||||
The first two items in the previous list are simply a way to conveniently preview your content as you write. This is a dynamic and fairly streamlined process. All the remaining items, however, are the same every time you want to add new content to the website. To make this repetitive process easier, I have adapted a script from the source repository for the [Chimer Arts & Maker Space](https://github.com/chimera/chimeraarts.org) website that is highlighted in the [Hugo Showcase](/showcase/). The script lives in a file called `deploy.sh` and has the following contents:
|
||||
|
||||
**Note:**
|
||||
|
||||
The first command `hugo` assumes you are running with all the default settings.
|
||||
|
||||
To use a theme, make sure to specify it with `-t ThemeName` instead (or include the theme in the config file).
|
||||
|
||||
hugo -t ThemeName
|
||||
|
||||
To build all draft posts *(If you only have drafts, no site will be generated)*
|
||||
|
||||
hugo --buildDrafts
|
||||
|
||||
**Deploy.sh:**
|
||||
|
||||
#!/bin/bash
|
||||
|
||||
echo -e "\033[0;32mDeploying updates to GitHub...\033[0m"
|
||||
|
||||
# Build the project.
|
||||
hugo
|
||||
cd public && git add --all && git commit -m "Publishing to gh-pages" & cd ..
|
||||
|
||||
# Add changes to git.
|
||||
git add -A
|
||||
If the changes in your local gh-pages branch look alright, push them to the remote repo:
|
||||
|
||||
# Commit changes.
|
||||
msg="rebuilding site `date`"
|
||||
if [ $# -eq 1 ]
|
||||
then msg="$1"
|
||||
fi
|
||||
git commit -m "$msg"
|
||||
git push upstream gh-pages
|
||||
|
||||
# Push source and build repos.
|
||||
git push origin master
|
||||
git subtree push --prefix=public git@github.com:spencerlyon2/hugo_gh_blog.git gh-pages
|
||||
After a short while you'll see the updated contents on your GitHub Pages site.
|
||||
|
||||
Now I can replace the last four items from our workflow list with a single command `bash deploy.sh`. This script accepts as an optional argument the commit message that git should use when committing your changes. If you wish to include a custom commit message, do so by putting it quotes after calling bash on the script: `bash deploy.sh "<my commit msg>"`. If you choose not to specify the commit message, one will be generated for you using the current time.
|
||||
### Putting it into a script
|
||||
|
||||
## Configure `git` Workflow, the Alternate Way
|
||||
The above uses a `git subtree` to deploy to Gits `gh-pages` branch. This works great, but with one drawback: It requires the generated content to be committed to the source branch.
|
||||
|
||||
There's another approach:
|
||||
|
||||
1. Set up your Hugo-site on `master`
|
||||
2. Create an orphaned `gh-pages` branch. (See [here](https://help.github.com/articles/creating-project-pages-manually/) for more information.)
|
||||
3. Follow the instructions below.
|
||||
|
||||
So, assuming you have your `gh-pages` set up, and `master` has a commit with some content you want to publish:
|
||||
To automate these steps, you can create a script _scripts/publish_to_ghpages.sh_ with the following contents:
|
||||
|
||||
```
|
||||
# Fetch the deployment script into the root of your source tree, make it executable.
|
||||
wget https://github.com/X1011/git-directory-deploy/raw/master/deploy.sh && chmod +x deploy.sh
|
||||
#!/bin/sh
|
||||
|
||||
# For setting it up to build to a folder other than "dist", see the options in deploy.sh.
|
||||
# Build the site to /dist.
|
||||
hugo -d dist
|
||||
DIR=$(dirname "$0")
|
||||
|
||||
# Run the deploy.sh script installed above.
|
||||
./deploy.sh
|
||||
cd $DIR/..
|
||||
|
||||
if [[ $(git status -s) ]]
|
||||
then
|
||||
echo "The working directory is dirty. Please commit any pending changes."
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
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 upstream/gh-pages
|
||||
|
||||
echo "Removing existing files"
|
||||
rm -rf public/*
|
||||
|
||||
echo "Generating site"
|
||||
hugo
|
||||
|
||||
echo "Updating gh-pages branch"
|
||||
cd public && git add --all && git commit -m "Publishing to gh-pages (publish.sh)"
|
||||
```
|
||||
|
||||
This will use the last commit as a base for the commit message to the `gh-pages` branch.
|
||||
This will abort if there are pending changes in the working directory and also makes sure that all previously existing output files are removed.
|
||||
Adjust the script to taste, e.g. to include the final push to the remote repository if you don't need to take a look at the gh-pages branch before pushing.
|
||||
|
||||
For more information about the deployment script, see this [README](https://github.com/X1011/git-directory-deploy).
|
||||
## Deployment with Git 2.4 and earlier
|
||||
|
||||
The `worktree` command was only introduced in Git 2.5.
|
||||
If you are still on an earlier version and cannot update, you can simply clone your local repo into the _public_ directory, only keeping the gh-pages branch:
|
||||
|
||||
git clone .git --branch gh-pages public
|
||||
|
||||
Having re-generated the site, you'd push back the gh-pages branch to your primary local repo:
|
||||
|
||||
cd public && git add --all && git commit -m "Publishing to gh-pages" && git push origin gh-pages
|
||||
|
||||
The other steps are the same as with the worktree approach.
|
||||
|
||||
## Hosting Personal/Organization Pages
|
||||
|
||||
|
@ -288,6 +185,13 @@ cd ..
|
|||
|
||||
That's it! Your personal page is running at [http://username.github.io/](http://username.github.io/) (after up to 10 minutes delay).
|
||||
|
||||
## Using a custom domain
|
||||
|
||||
If you'd like to use a custom domain for your GitHub Pages site, create a file _static/CNAME_ with the domain name as its sole contents.
|
||||
This will put the CNAME file to the root of the published site as required by GitHub Pages.
|
||||
|
||||
Refer to the [official documentation](https://help.github.com/articles/using-a-custom-domain-with-github-pages/) for further information.
|
||||
|
||||
## Conclusion
|
||||
|
||||
Hopefully this tutorial helped you get your website off its feet and out into the open! If you have any further questions, feel free to contact the community through the [discussion forum](/community/mailing-list/).
|
||||
Hopefully this tutorial helped you to get your website off its feet and out into the open! If you have any further questions, feel free to contact the community through the [discussion forum](/community/mailing-list/).
|
||||
|
|
Loading…
Reference in a new issue