How to Build and Deploy a Static Jekyll Site with Github Pages
Update (2020/05/10) - Fixed incorrect commands and added more precaution notes.
One of the great things about Jekyll is that it has close integration with Github Pages, which means you can let Github host and publish your website with just a few config changes. There are a lot of guides (for example, the official Github documentation) that talk about how to set it up, so I won’t go over it here. Within a few minutes, I was able to get my site up and running, and I was amazed at how easy it was to do that, but later on I ran into some issues that caused me to change my entire setup completely.
The way that is works is that you push all your code into the master branch, and then you create (or let Github create) another branch called gh-pages. Github will automatically render the page based on the source that resides on that branch. Therefore my workflow before consisted of the following:
- Make changes on
masterbranch, commit/push to remote - Switch to
gh-pagesbranch, merge changes from master to branch, commit/push to remotegh-pagesbranch - Github will automatically render what’s on
gh-pages
The biggest problem with this is that Github Pages does not support custom Jekyll plugins. I was troubleshooting with another issue where the solution required using a custom component, and that’s when I realized that the current set up is a deal breaker for me. I decided to find out a different way of deploying my website while still using Github Pages. After some googling, I found that it’s possible to deploy only the static pages (all the content in _site folder), which contain the files post rendering by Jekyll. This required doing some Git trickery, and after consulting with various solutions, this is what has worked for me.
Make gh-pages only contain the generated HTML files
This is what the new setup would look like.
masterbranch would only contain the source files (_sitefolder is ignored)gh-pagesbranch would only contain what’s in_sitefolder, and has no knowledge of files outside of it (and from its view, the content of_sitefolder is the root)
But by default in Git, you cannot have two branches that point to a different root. I’ve considered doing something with Git submodules but the downside to that is that master branch would end up keeping track of all the files in _site folder, which means I end up duplicating the _site content, which is not ideal.
Solution is to put another git repo inside the _site folder
The current git repo would continue pointing to the master branch as before (with _site folder ignored), and then the 2nd git repo would be created inside the _site folder so it would have no knowledge of what’s outside of that folder. The 2nd repo would be pointing to the gh-pages branch so it would not conflict with the master branch.
Here are the git commands to help you get set up:
// First push all source files to origin master
$ git init
$ git add .
$ git remote add origin ssh://git@github.com:username/project.git
$ git push origin master
Now gitignore the _site folder
$ echo "_site" > .gitignore
$ git add .
$ git commit -m "adding gitignore"
$ git push origin master
Now clone the 2nd repo, delete the master branch in the new repo:
$ cd _site
// Make sure this directory by deleting all the files inside
$ git clone git@github.com:username/project.git .
$ git checkout origin/gh-pages -b gh-pages
// Delete the master branch
$ git branch -d master
// Now locally delete all the files - but keep the .git folder
Build the Jekyll site locally to generate the HTMl files, then push
$ cd ..
$ bundle exec jekyll build
$ cd _site
$ git add .
$ git commit -m "Deploying build"
$ git push origin gh-pages
In the project root repo, make sure there is no gh-pages branch, and you’re all set!
Make sure that you put an empty file called .nojekyll file in the project root folder, so then Jekyll will put that file in _site folder, and Github Pages will not try to render what’s in _site folder as a Jekyll site. It will just display a static site instead.
Caution: Be careful not to run bundle exec jekyll clean as this will remove all the files inside the _site folder, so I recommend performing manual cleaning instead.
Now this is the new workflow using the new set up. Follow the steps below once you are finished making changes in your source and you want to deploy the new site to Github Pages.
- Run
bundle exec jekyll buildin project root folder - Run
cd _site - Run
git add . - Run
git commit -m "Commit Message Here" - Run
git push origin gh-pages
Here is a simple bash script called deploy.sh that will do all the above commands (except for the build command) for you:
#!/usr/bin/env bash
if [[ -z "$1" ]]; then
echo "Please enter a git commit message"
exit
fi
cd _site && \
git add . && \
git commit -m "$1" && \
git push origin gh-pages && \
cd .. && \
echo "Successfully built and pushed gh-pages to Github."
Make sure you give permission for the script to run:
chmod +x deploy.sh
To run, just type this:
$ ./deploy.sh "Your Commit Message Here"
And that’s it! I got the best of both worlds where I get to keep track the source and the generated files on separate branches (thus avoided having to keep track of duplicate files), and I got to be able to use custom Jekyll plugins!
Leave a comment