Automatically updating your website with Git and git-hooks

*This process works with sites hosted on NearlyFreeSpeech.net. I’m not sure how well it’ll work on other hosts, though I assume the process should be similar.

I was jealous of all of my friends with their pretty websites, so I decided that I would go ahead and build my own. Looking into all the options out there, I decided that I’d host my site on NearlyFreeSpeech.net(NFS) because it was cheapest (literally $0.01 a day!), and gave me the most control over my site.

After buying the “justsophie.com” domain, I had nice little space on the internet where I could make myself cozy. I just had to populate it! Typically, updating a site requires one to SSH or FTP assets to the server, which is really annoying if you make lots of changes. And because I’m lazy, I decided to automate this process by using Git hooks. (Laziness FTW :D)

What we have to do is create an empty Git repo on your website with a post-receive hook that will take the updated files and put them in the public facing folder! I’m assuming you know how push/pull, commits, etc work in Git. Let me know if you don’t!

On your computer:
We’ll need to create a new git folder for all the assets of our website. Go on and create a new repo on Github and clone it to your local computer. I’m just going to use this website as an example.

git clone https://github.com/srli/Pomelo

All set for now, let’s go set up the stuff on NFS.

Website side:
SSH into your website
NFS provides your site with a bunch of folders on start, but the two important ones are:

public/     <–Your public internet facing files
private/   <–Files only you can access

In your private/ folder, create a new git folder and create/initialize an empty git repository in it, give it a descriptive name:

mkdir git && cd git
mkdir mysite.git && cd mysite.git
git init --bare

A bare git repo stores no files, and traditionally has a .git extension. We’ll use this bare repo has the home for our git hook. Read great explanation of the difference between bare git repo and a normal one here.

After you’ve initialized the bare repo, you should see a bunch of folders. cd into the “hooks” folder. We’ll be modifying the “post-receive” hook. So:

cd hooks
mv post-receive.sample post-receive
vim post-receive

Then paste the following code into vim. Delete all the stuff that’s there already.

#!/bin/sh
REPONAME='mysite'

GIT_REPO=$HOME/git/$REPONAME.git
TMP_GIT_CLONE=$HOME/tmp_deploy/$REPONAME
PUBLIC_WWW=/home/public
rm -rf $TMP_GIT_CLONE
git clone $GIT_REPO $TMP_GIT_CLONE

rm -Rf $PUBLIC_WWW/*
cp -rfv $TMP_GIT_CLONE/* $PUBLIC_WWW
rm -Rf $TMP_GIT_CLONE
exit 0

Afterwards, we need to quit vim, so:
:q

As you can see in the code, we first download the files from Github into a temporary folder under the private folder, then move everything over to the public folder. Let’s make that now:

cd /home/private
mkdir tmp_deploy

Finally, make the post-receive hook executable so it can actually run.

chmod ug+x mysite.git/hooks/post-receive

Ok, that’s all set for the website side stuff.

Back to the computer:
Going back to the cloned git repo from before, we need to set up a remote now. When we push to this remote, we’ll be sending a post-receive signal to the empty git repo on the website, which will cause it to go to the Github and download all the new files.

cd into the git repo. List the current remotes that are there:

git remote -v

You should see the origin remote which pushes your stuff to Github by default. Now we need to add a remote that pushes to the empty git repo on our website.

git remote add website_remote ssh://YOUR_USERNAME@ssh.phx.nearlyfreespeech.net/home/private/git/mysite.git

^Everything here is one line, it wouldn’t fit in one. 🙁

Now when you want to push something to your website, simply type:

git push website_remote

enter your password, and all your changes will automatically be reflected on the website! How cool is that!

-Sophie

3 Comments

  1. John

    Seems like git doesn’t have a post-receive.sample file anymore. Doesn’t matter though, the whole line (mv post-receive.sample post-receive) can be omitted.

  2. Hey, thanks for the guide! I tried a few methods, but yours worked best!

    However, I had to change one thing to make it work. My command to push had to be:

    $ git push website_remote master

    Maybe it’s just how git behaves now.

Leave a Reply

Your email address will not be published. Required fields are marked *