All blog posts that explain how to publish your site sources to github.io from a Hakyll build suggest to use the
_site directory as a git submodule. After a few experiments, I came to the conclusion that doing this can lead to some trouble. I explain in this post why, and detail the workaround I use instead.
Most of the times, you build your site sources with:
cabal run build
and all is perfect. The directory
_site is updated and, in case you declared
_site as a submodule, everything is fine and the contents of the submodule are correctly updated. The only precaution to take is to be sure that
_site is not on a ‘detached HEAD’ state.
Imagine now that you run instead:
cabal run rebuild
In this case, you can notice that hakyll first wipes out the directories
_site. What happens then? git-submodule is now wrecked out, and, because
_site/.git has been deleted, the directory
_site is considered as a standard subdirectory in your source tree instead of a submodule! Indeed, if you go in the directory
_site and for example run
git remote -v, you will see that
origin points to the location of you Hakyll source tree, not to the location of your
github.io repository where you push the source site files!
Why did this happen? Because the
rebuild process first involves the deletion of the
_site directory. Hence the
Hopefully you can recover from this situation. Go to the Hakyll source tree and run:
git submodule udpate --remote
To avoid this problem, it is necessary to use two separate directories for the build directory used by Hakyll, and the git submodule used to push the files of your website to github. Hakyll uses
_site as a build directory, and I created a submodule in
To summarise, the build/update process involves these steps:
- hakyll build
- set your build submodule (e.g.
site) to the default branch (e.g.
_siteto your build submodule (e.g.
site). Do not delete the
- git push to github
I pushed all of this in a minimalist
Makefile (my submodule lies in
.PHONY: build rebuild watch build: cabal run $@ rebuild: cabal run $@ watch: cabal run $@ push: rebuild git submodule update --remote --merge rsync -avr --delete --exclude='.git' _site/ site/ cd site \ && git checkout master \ && git add . \ && git commit -m 'site update' \ && git push origin master git add site git commit -m 'site update' git push origin master