Jekyll works just fine on my laptop. If I continue hosting this site on my own web host, I don’t have to restrict my Jekyll configuration to what GitHub gives me – that opens up the full range of available plugins. It also means that I can drag over some content from other places on the server, if I want to. Like my resume? Yeah, that.
uploading with rsync
So, what does it take to deploy from my laptop? Not much: two lines in my Makefile.
upload: build rsync -a _site savitzky.net:vv/web/computer-curmudgeon.com
Well, I ought to add the build recipe, too, but that’s been in there for a while.
build: JEKYLL_ENV=production $(JEKYLL) build if [ ! -d _site/.well-known ] && [ -d .well-known ]; then \ cp -r .well-known _site; \ fi
This is doing two things. First, it builds the site with the
environment set to “production”, which changes a few things in the page
heads. It also makes sure that the
.well-known directory is still there,
and copies it from the current directory if it isn’t. It’s used for renewing
the site’s Let’s Encrypt certificate, so we really
want to make sure it’s there.
Anyway, now I can say
make upload at the command line and the site will get
rebuilt and uploaded.
There’s another way: do it with git.
uploading with git
Git is actually a very efficient way of transferring files. You can even use it for file-sharing: SparkleShare uses it to make what amounts to a private Dropbox clone. It’s also the only way I know of to get build products onto GitHub. So let’s do that.
First, we need a branch. We’ll call it “prod”, build the site again, and this time add Jekyll’s build destination to it.
git checkout -b prod make build git add -f _site git commit -m "start of prod branch" git push origin prod
We need to use
add -f because the
_site directory is in the master
.gitignore file; we only have to do that the first time.
Now I can ssh to my web host and set up the website’s working tree there:
cd vv/web/computer-curmudgeon.com/ git fetch origin prod git checkout prod
From there on it’s pretty simple, because the branch structure is already set
up. All I have to do is
git push on the laptop, and
git pull on the host.
git checkout prod git merge -s recursive -X theirs master make build git commit -a -m "prod build `date`" git push ssh savitzky.net git -C vv/web/computer-curmudgeon.com pull git checkout master
I probably won’t need the
-s recursive -X theirs options the next time I
merge. They were needed this time because I forgot to go back to the master
branch before I made changes. Oops! (What those options do is avoid
conflicts by simply dropping any local changes. I can get away with it
because the prod branch is supposed to be only for builds.)
The ssh command is only needed until I install a suitable hook on the server.
You’ll note the
-C option, which changes to the given directory before
running the subcommand. You’ll also notice that you can run a command with
ssh – you don’t have to log in and do things by hand.
The one problem with this scheme is that it leaves your history looking rather messy, but the master branch still stays clean, and the merges give you a good record of which changes go with which build.
You might think that you could make things simpler by rebasing the prod
branch rather than merging into it. You’d be wrong. I tried that, just once,
and it made things even more of a mess, requiring a
push -f to get the code
onto the server, and a hard reset instead of a pull to update the prod branch
on the server. No thanks. See the section “RECOVERING FROM UPSTREAM REBASE”
in the man page for