Ayende @ Rahien

My name is Oren Eini
Founder of Hibernating Rhinos LTD and RavenDB.
You can reach me by phone or email:


+972 52-548-6969

, @ Q c

Posts: 6,026 | Comments: 44,842

filter by tags archive

Primitive Git Auto Deploy

time to read 1 min | 100 words

Following my post yesterday, I decided that for now, we will have the following system:

  • A github hosted repository with the binaries
  • A github hook to post on notification
  • A server side listener that would get that notification

On push, we will simply call git pull in the website directory. We use git ignores for the logs & data files, but that is about it.

It is primitive in the extreme, and it likely have many failure scenarios, but for now, it works. And very nicely, too.



Sounds like what I used for a small website when I was trying out Ruby on Rails.

Paul Cowan

Deployment is a good extension of a package manager. Perhaps openwrap or maybe less so nuget might be a good mechanism for deployment.

Wih openwarp at least the hooks are in place during the build process.


But how deal you with the loadbalancer? Or don't you have loadbalanced websites? Is git also making changes to the configuration files (web.config)? That could be problematic with service bus addresses..

How is git going to revert the operation when something goes wrong? But to be honest, I don't want to think about the possibility that I have a new release on 6 webservers and than have to find out something went wrong.

Usually I get one server from the pool and make that my live test server. I copy the current database run the update scripts on the new database. Than I update the connectionstring from my testserver to use the new database. On that webserver I also run a full regression test suite. If nothing is wrong, I copy back the old config files and pull the second server from the pool and update that one as well. Than I pull all the other webservers from the pool, update the master database and put webserver 1 & 2 back in the pool. Than I monitor the release (error 500 messages, logs) for a minute of five and finally I update the rest of the webservers one by one and add them to the pool aswell..

In the past I have tried (in our test environment) several web deployment tools where a build system creates the release and copy the release files to a specified location. The deployment tools take up the deployment from there. But none of them are really suited for a busy production environment when something goes wrong.

Using transactions you can make a atomic update to your database. But at a certain point you have to commit the 'master' transaction. As soon the webservers are online again that will make database content updates (customer details, order (item) details, etc). So how are you going to revert a release without loosing the new data?

A production releases are a two man job at our company. Much like in an airplane cockpit we perform the several tasks and the other person have to confirm the action. We work in the financial sector (stock markets, loans, insurances, etc), so a release have to be 100% every time. And with a 99,999% uptime SLA (= less that 5.5 minutes of downtime per year) we also can't afford a release that did go wrong.

Software should make you life easier, not take you out of the loop. And manually update 6 webservers takes an average of 20 minutes. That 20 minutes includes several verification points.

Desktop release are a bit easier. I only need to send a message to a UDP broadcast address and all running clients will check for updates, download the new assemblies and restart the application (we don't use clickone, but have a similar update process).

Daniel Hoelbling

Ayende, there is a way to use a bare repository for what you do.

By using a post-receive-hook you can do a git checkout -f to your webapp-folder from the bare repo.

So you push to the repo, and once the push is received the repo runs the post-receive-hook script to deploy the app..



I think what Oren wants here is a super simple deployment for a super simple site. No soa, no complex configuration or webfarms.

KISS applies here. why bother with a CI / deployment infrastructure when you have a simple personal site.

I've used this too with subversion for a personal/static site.


Ayende Rahien


Did you see the title? I said primitive, and I meant primitive. This is for a simple site, no load balancing.

Git is also tracking the config changes, yes.

Reverting is as simple as doing something like: git checkout previous-version-hash

A more complete process would be something like:

  • Addresses are either static or calculated, the config file is shared among all servers.

  • You do one live test on one of the servers. When you are through, you basically do something like this (scripted, of course):

** loadBalancer.TakeOut(server1);

** execute on server1: git pull

** loadBalancer.Bring(server1);

In general, you don't do anything in the release manually, it has to be scripted. Otherwise it wouldn't work the same way all the time.

Ayende Rahien


Thanks for the info

There might be problems with that approach regarding versioning, conflict detections, etc.

I want the process to break if we locally modified something (stupid to do, but happens)

Daniel Hoelbling


Then you can use the pre-commit-hook (i think its called that way) to do that.

There is one before receive that can fail and one after that can only output messages.

You could try doing a dry-run if that's possible on a checkout.

I'd have to look up how to fail this early. But it should work..

Greeting Daniel.

Daniel Hoelbling

Ah found it:



If your script returns anything besides 0 it will not update any refs in the remote repository.

Now you could use a non-bare repository in your inetPub folder (that's a clone of your bare repo you push to on the same server).

If you push to the bare-repo you run the pre-receive hook that runs a git status on your non-bare repo (that contains the app), if nothing changed it will allow you to proceed and receive the commits.

Afterwards you can run the post-receive hook that goes to your non-bare repo and does a git pull ..

But this is not really the most elegant way I can think of, and it's prone to errors once you do non-fast-forward pushes (eg. amending or rebasing) where you'd have to go to your server and re-clone the non-bare repo)..

I'd suggest using only one reop you push to that does a git checkout to a folder.. Since you can run scripts there you could even checkout to a new folder every time and use powershell to redirect IIS to that new folder, leaving the old site intact.. (Not really satisfactory either)

greetings Daniel

Comment preview

Comments have been closed on this topic.


No future posts left, oh my!


  1. Technical observations from my wife (3):
    13 Nov 2015 - Production issues
  2. Production postmortem (13):
    13 Nov 2015 - The case of the “it is slow on that machine (only)”
  3. Speaking (5):
    09 Nov 2015 - Community talk in Kiev, Ukraine–What does it take to be a good developer
  4. Find the bug (5):
    11 Sep 2015 - The concurrent memory buster
  5. Buffer allocation strategies (3):
    09 Sep 2015 - Bad usage patterns
View all series


Main feed Feed Stats
Comments feed   Comments Feed Stats