Git: managing a website using hooks


Git is a very powerful tool when coding. It has bothered me for a while now that I didn’t know how to use it to push changes to a website server. Finally I decided to do some digging and figured it out.
In order to avoid having the actual repository in the website’s directory on the server side, we’re going to initialize the repository on the remote server, then have git update a different folder with the changes we made every time we push something from our working machine.

Setting up the server-side

First off, we’ll need to have ssh access to the webserver. Then, we can initialize a new bare repository for our website. That process may look something like this:

$ ssh user@server
Last login: ...
(user@server) [~]$ mkdir repos && cd repos
(user@server) [repos]$ git init --bare my_website.git

See my article on Setting up a Raspberry Pi as a Git server for a more detailed explanation.

Next, we need to add a hook to update the directory where our live site resides.

Git hooks

In git terminology, a “hook” is a script that is executed every time a certain event occurs. There are a variety of events, and you can run any kind of executable script: shell, Python, etc. Have a look at the official documentation page for more information on how hooks work.
In this case, we want to add a hook to update our website’s directory every time changes are pushed to the repository. We will use a post-update hook for this, which will run after a change is pushed to the repository. In order to create (or activate) a hook we must create a file with the corresponding name (no extensions) in the hooks subdirectory of our repository:

(user@server) [repos]$ cd my_website.git/hooks
(user@server) [repos/my_website.git/hooks]$ vim post-update

This file should contain something similar to:

## Set work tree to our site's directory and
##  check out the changes made by the commit:
GIT_WORK_TREE=/www/web/ git checkout -f

The exact path of the website’s working directory depends on your setup, of course. You can use pwd to find out what it looks like on your webserver.

Last but not least, we must make that file executable:

(user@server) [repos/my_website.git/hooks]$ chmod +x post-update

That’s it for the server side. Now we need to set up the client side’s git repository to push commits to our website.

Setting up the client-side

This is actually very simple. There are two scenarios here: if this is the first time you’re setting this system up, you’ll likely have an empty server-side repository (no commits yet), and some files on the local machine to push. If, however, you’re setting this up for a second machine, you’ll want to clone the existing repository down.

Option 1: push the local version to a blank server repository

If our working directory is not yet set up to be a git repository, we’ll do that first:

$ cd my_website
$ git init .
$ git add . && git commit -m "Initial commit"

Next, we want to create a new remote (here called web), and set the master branch to synchronize with our server:

$ git remote add web my_user@my_server:/www/web/repos/my_website.git/
$ git push --set-upstream web master

Option 2: clone the remote repository

All we need to do is clone the remote repo:

$ git clone my_user@my_server:/www/web/repos/my_website.git/
$ ls

And we’re done!
From now on, every time we git push a commit, it will be automatically added to the live website!