What are examples of useful git hooks

Git deployment

Those who run websites are more often faced with the problem of how the easiest way to transfer project updates to the live version. Especially with smaller projects, there is a tendency to resort to simple but error-prone methods such as simple FTP uploads.

There are of course a number of different methods of solving the deployment. But here we would like to go into a little more detail about the possibilities that can be achieved with the help of Git, the tool for versioning software projects.

In each of these cases, the live project must be set up as a Git repository. A simple one in the root directory of the project is usually sufficient. If you already have an existing repository, you can of course simply clone it to the server.

An additional bonus when setting up the project with Git: If you have discovered an error after making the changes, you can often easily undo the changes with a "revert" commit or one (of course, database migrations are not included).

In order to simplify the explanations a bit, we assume in the following that we have a productive server, which has the root directory of the live project in the directory. The server's domain is. Git and SSH are installed on the server and have already been converted into a Git repository, which we will refer to as the "Live Repository" from now on.

Git "bare" repositories

We would like our normal Git “workflow” not to change (or only to a limited extent). Ideally, you would be able to see the changes immediately in the live system with a single repository shared by the development team. A simple "push" into the live repository is usually not possible without further ado.

For this reason, we need a second, so-called “bare” repository on the productive server, which we will use as a “remote” on all local repositories. We create the bare repository in the directory:

$ mkdir /var/www/live.git $ cd /var/www/live.git $ git init --bare

Next we enter this "bare repository" as a remote in the live repository:

$ cd / var / www / live $ git remote add live-bare /var/www/live.git

And push all commits (if there are already commits) to the new remote:

$ git push live-bare master

It should now be possible to clone the repository on the local computer:

$ git clone ssh: //example.de: /var/www/live.git

When using SSH, we recommend using SSH keys, but we will not go into that here.

Configure hooks

After we have cloned the bare repository locally, we can push changes to it on the server. At the moment, these are not yet in the live repository. To achieve this, we use a little trick: Instead of pushing the changes directly into the live repository, we use a hook from the bare repository to "pull" the changes from the live repository.

So we create a hook, with the correct file rights, in the bare repository:

$ touch /var/www/live.git/hooks/post-update $ chmod ugo + x /var/www/live.git/hooks/post-update

We enter the following script in the file:

#! / bin / sh # Determine the current branch branch = $ (git rev-parse --symbolic --abbrev-ref $ 1) # Note only branch "master". Could also be a different branch. if ["$ branch" = "master"]; then cd / var / www / live || exit unset GIT_DIR echo echo "*** Pulling changes from $ branch master into $ (pwd) repository." echo git pull live-bare "$ branch" fi exec git update-server-info

The process is simple: if an update has taken place on the bare repository in the "master" branch, the script changes to the directory of the live repository and fetches these changes from the remote "live-bare". Every push to the “master” branch in the bare repository is thus immediately visible in the live repository.

If you also have a development copy on the productive server, for example in the directory (which can then be accessed via a different domain), the script could be expanded to include a case distinction for the branch “dev” so that a push would switch to “dev” becomes "master" after a push.

Bitbucket / Github webhooks

If you use Bitbucket or Github, the bare repository on our production server is not necessary, as the repositories can be used as our bare repository by the hosters. So that we can update our live system automatically when a push is sent to the hosters, we use the so-called "webhooks" that are provided by both services.

In the settings of a repository at Bitbucket or Github you will find the entry "Webhooks" or "Webhooks & Services". There you can specify that a URL is called up for certain events in the repository. In the case of Bitbucket with an HTTP POST request and a JSON formatted payload.

In the following we look at an example with Bitbucket and start by entering a (non-existent) example Bitbucket repository as a remote in our live repository:

$ cd / var / www / live $ git remote add bitbucket [email protected]: example / live.git

We assume that the project has already been fully pushed to Bitbucket (e.g. from a local computer).

If the server uses PHP, setting up a webhook is pretty easy. For example, you could create the file and fill it with the following content:

The webhook.php expects an argument with a self-chosen "password". In the webhooks settings in the Bitbucket repository we can now create a new webhook and transfer the following URL to it:


We leave the “Trigger” on the preset entry “Repository push”.

Finally we have to look at the point “Deployment keys” in the repository settings (“Deploy keys” on Github). Deployment keys are there to get read access to the repositories via SSH. These are normal SSH keys.

This is especially necessary if the repository is private. If the repository is public, you can also enter the public HTTPS URL in the live repository as a remote - a deployment key is then not required.

The deployment key should be generated without a "passphrase", otherwise the automated pulling is not possible:

$ ssh-keygen Generating public / private rsa key pair. Enter file in which to save the key (~ / .ssh / id_rsa): deploy_key Enter passphrase (empty for no passphrase): Enter same passphrase again: ...

You should be careful not to overwrite the standard key file if you already have a key there.

If you enter "deploy_key" as shown above, the tool creates two files in the current directory: and.

The content of the is copied into a new entry in the "Deployment keys" in the Bitbucket repository settings. You upload them to the productive server. You could reload the file, with the home directory of the user who will do the pull at the end, i.e. the user who executes the PHP script. If you don't want to change it, you can create a new host entry in the, something like this:

Host bitbucket-deployment HostName bitbucket.org IdentityFile ~ / .ssh / deploy_key

And change the remote in the live repository:

$ git remote set-url bitbucket git @ bitbucket-deployment: example / live.git

If everything has been done correctly, a push to the Bitbucket repository should now automatically execute an HTTP POST request, which in turn carries out one from the Bitbucket repository.

The different strategies can of course be combined in any way. It would also be possible to enter several remotes locally to allow a stricter separation between remote development and remote production. In the end, that's up to you.


Posted in web developmentgit deployment