This post is about , which is powered by and hosted through GitHub using . I’ll describe the workflow I use when deploying new posts. my blog Pelican GitHub Pages For those of you not familiar with these technologies, Pelican is a static site generator — meaning you can write your content in a format such as /Jupyter notebooks, and Pelican will automatically generate the HTML files for you; and GitHub Pages is a service provided by GitHub for hosting a website under the <your-username>.github.io URL. Markdown Using Pelican and GitHub Pages is quite easy. There’s one annoying little thing though… GitHub Pages assumes the branch contains the root folder to be served to the world. If you're using Pelican's default settings, the folder is the folder you want to serve. contains the generated website's files. A natural choice of how to organize the files inside the repository would be to define pelican's root folder - the parent of - as the root of the repository. But GitHub Pages needs to be the root. Bummer... master output output output output There are who solve it using two separate repositories: one for the website “source” files, and one for the output which will be served using GitHub Pages. those I personally don’t like breaking my blog into two repositories. I want to keep everything in one place, so I chose to solve the problem using branches and git hooks. The first step is to create two branches: will contain the blog's "source" files, namely - all the files such as the folder which contains the actual posts, and file. source content pelicanconf.p will contain only the contents of . master output These branches will obviously live in my GitHub Pages repo ( ), and since the branch contains 's contents, a user navigating to will be presented with the goodness of my blog. https://github.com/yoel-zeldes/yoel-zeldes.github.io master output yoel-zeldes.github.io Unfortunately, manually maintaining these two branches is cumbersome. Git hooks to the rescue! Git has a mechanism to execute custom scripts when certain important actions occur. In my case, whenever I push a commit to the branch, I'd like the branch to get updated with the new contents of . This can be done using the pre-push hook, which is executed - you guessed it - just before a push occurs. source master output All you have to do is create a file named with : .git/hooks/pre-push the following content #!/bin/sh while read local_ref local_sha remote_ref remote_sha do if [ "$remote_ref" = "refs/heads/source" ] then echo 'pushing output folder (production version) to master...' pelican content -o output -s publishconf.py echo anotherdatum.com > output/CNAME ghp-import output git push --no-verify git@github.com:yoel-zeldes/yoel-zeldes.github.io.git gh-pages:master pelican content -o output fi done exit 0 The first thing the script does is iterating over the commits that are about to be pushed. Specifically, only commits that are pushed to the branch are of interest to us. source If commits are pushed to , it executes command using . This will generate the production version of the blog into . source pelican publishconf.py output It then creates a file, which is needed since I use a custom domain ( ). CNAME http://anotherdatum.com The tool is used for copying the contents of to a branch named . GitHub Pages Import output gh-pages is pushed to the remote branch. skips the pre-push hook so this script won't run again. gh-pages master --no-verify is executed again to generate the development version of my blog, so I'll be able to write the next post. pelican Now, whenever I push to , and only to , gets updated with the new contents. Cool! source source master One last small detail: I added to the file. This way, the branch won't include this folder. We don't really want to put it under version control - it would be like putting other types of generated files such as or under version control. output .gitignore source .pyc .o Originally published at anotherdatum.com .