Jens Segers on

Deploying websites with Git (and Composer)

I have been using Git to deploy my websites for quite some time now. It is so much easier than having to drag 'n drop files with FTP or SFTP. When I switched to Laravel 4 earlier this year, I updated the script to automatically update composer packages.

To deploy a website using Git you basically have to set up 2 repositories; one on your workstation and one on the webserver with the actual live "production" code. You push changes from your workstation to the "production" repository, where a Git post-receive hook will update the live code.


Start by initialising a non-bare Git repository in your website's directory:

> cd /var/www/website
> git init
Initialized empty Git repository in /var/www/website/.git/

After this we need a post-receive hook that will make sure that any time anything is pushed to the repository, the live code is updated. These hooks are custom scripts that are executed when certain important events occur, and are located in the .git/hooks directory. In this case we need to create the .git/hooks/post-receive hook with the following content:


# Update the working tree after changes have been pushed here
cd ..
env -i git checkout -f

# Check if a composer.json file is present
if [ -f composer.json ]; then

    # Install or update packages specified in the lock file
    composer install


The first lines update the live code with the changes that are pushed, and the part below checks if a composer.json file is present. The composer install command will install or update your packages with the versions specified in the composer.lock file, so make sure this file is not in your .gitignore file. This way, your remote host will always have the same package versions as your workstation. For more information about this lock file, and why it should not be in your .gitignore file check:

Ensure the hook is executable:

> chmod +x .git/hooks/post-receive

To be able to push to a non-bare repository you need to execute the following command:

> git config receive.denyCurrentBranch ignore


The only thing that is left is to add the correct remote to the website's repository on your workstation:

> git remote add production ssh://

To test if everything is working, modify something and push it to the newly created production remote:

> touch test
> git add test
> git commit -m "Testing deployment"
> git push production master
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 268 bytes, done.
Total 2 (delta 1), reused 0 (delta 0)
remote: Composer up to date
To ssh://
   cf43bc5..96f33d8  master -> master


Tweet about this blog post and you will appear below!