Rapid Deployment with Git (Insecure)

Warning:┬áThe technique illustrated in this walkthrough is insecure. I’ve created a revised version without this problem, but am leaving this post here for awareness. Read this article and my comments immediately below to learn about the security problem and avoid it in your future work, and don’t hesitate to ask me anything if you’re unsure about the problem.

This walkthrough assumes you have an existing project and Git repository, and that you want to set up easy and quick remote deployment – maybe to a web server.

This technique can be used for any project where you’re comfortable with simply pushing updates to a location and seeing them immediately active.

This works great for code bases like the one for this blog or any basic website you may be managing. However with larger projects that need automated testing and CI, etcetera, it may not be sufficient.

If this suits your needs, you’ll save a whole heap of time whenever you need to update a destination with your changes.

The final assumptions are that Git is installed and usable at the destination (if it’s not, you can easily add it following this guide), and that you won’t actually be coding or making any direct changes at the destination. Instead we’ll push in any changes and trust me, when you see how easy it is, you won’t need to make on-the-server/spot changes ever again – even for hotfixes and tiny bugs.


I’ll propose a hypothetical situation and walk you through the setup and usage for it. In reality you’ll have to adapt this guide to your own situation. You shouldn’t think of this as a bad thing though, as it will give you the opportunity to extend the solution however you feel and let it do more work for you.


I’ve got a website, www.bilalakil.me, that I update frequently. I code these updates from my home PC (hypothetical scenario >.>) or from Cloud9 when I’m on the go – so I never actually work on the webserver itself, I just upload my changes to it.

For my changes to become visible I’m used to (but not happy with) manually uploading them to my webserver under the ~/www/wp-content/themes/bilalakil/ folder, using my username: useruser and a password which I’ll never tell you.

I just wish I can easily and quickly get my webserver using my local or Cloud9 changes without having to deal with any tedious, annoying uploading or file syncing… sigh.

I want to push my changes to it.

Setup steps

Open your terminal and follow these instructions. You’ll have to appropriate them for your individual and unique situation though, so try to understand what’s going on.

  1. SSH into destination server:
    ssh useruser@bilalakil.me
    Enter your password when prompted. We’re┬átargeting the server that you want to deploy your pushes to – we’ll set up a Git repository here.
  2. Clone your existing repository as a bare repository:
    git clone --bare https://bilalakil@bitbucket.org/bilalakil/superepository.git/ ~/deployment.git/
    You’ll probably need to enter your password when prompted here too. In this case, it’d be a Bitbucket password.
  3. Create and enable the post-update hook:
    cd ~/deployment.git/hooks/
    mv post-update.sample post-update
    cat << EOF > post-update
    cd ~/www/wp-content/themes/bilalakil/
    git --git-dir=.git fetch
    git --git-dir=.git reset --hard origin/master

    The CD command in the post-update script should be targeting the final destination for your deployed code. That should be where you would’ve manually uploaded your code if you didn’t know about this procedure.
  4. CD to final destination:
    cd ~/www/wp-content/themes/bilalakil/
    As mentioned in the previous step, this is where you want the contents of your Git repository to end up and be operational after deployment.
  5. Initialise working-copy Git:
    git init
  6. Add deployment folder as origin and reset to it:
    git remote add origin ~/deployment.git/
    git fetch
    git reset --hard origin/master

This will discard any differences between what was already at the destination and what the master branch of your Git repository looked like. Your destination folder will now be up to date with what you specified as your origin.

You should keep in mind one of the aforementioned assumptions: you shouldn’t be making edits from the destination. They’ll be lost in that last step and whenever you push to the deployment repository.

The server should now be ready to receive pushes to the deployment repository and automagically have those changes mirrored to where they’re needed.


From each of your working copy Git repositories that you’ll push to the setup server from, you need to:

  1. Add the deployment repository as a remote:
    git remote add deployment useruser@bilalakil.me:/home/useruser/deployment.git/
  2. Push to it when you want your code to be immediately deployed:
    git push deployment or git push deployment <localbranchname>:master if you’re working on a branch other than master.

That’s everything!

Note that under this setup you must push to the deployment master branch even if the branch you’re working on isn’t master, because that’s what the final destination will target and reflect with it’s reset --hard command.

Author: Bilal Akil

Husband of Joy. Programming hobbyist and professional.

2 thoughts on “Rapid Deployment with Git (Insecure)”

  1. Warning: The practice illustrated above is insecure. Read this comment to understand why, and why this article still exists.

    Although this technique is simple and handy, it is not very safe and should not be used in situations when security or privacy is important, such as with production code.

    An exploit exists in the fact that a Git folder is exposed to public (~/www/wp-content/themes/bilalakil/.git in the example above) (unless you’ve explicitly hidden it, i.e. with a .htaccess file), and can be easily browsed to by those who know, exposing all of the underlying files and code.

    If privacy isn’t so important, for instance with open source software that does not contain any keys or passwords within, this could still be fine to use. However, it’d probably still be wise to avoid, if only as a matter of exercising good practice.

    I am in the process of writing a follow-up post on a more secure version. It will be linked to this post once complete.

    1. That revised post is now complete and even simpler to get going with than this one.

      I’ll be leaving this post here as an educational piece (with a glaring warning). Perhaps some others can happen across and learn of this security hole.

Leave a Reply

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