Deploying websites with Git

Posted: 2010-02-23
Category: Git

Back in 2008 I wrote an article describing how you can use Subversion as a very simple deployment method from your local box, through testing environments to your live servers. Since then I have been using Git to track all client work and personal projects, so I modified this approach to work with Git.

It sounds a little crazy to some people, but really deploying websites with a version control system makes a lot of sense. When you develop on your local box you can change any number of files throughout a codebase and trying to manually remember what files have been changed can be a pain in the nadgers.

You either need to use your VCS (Subversion, Git, Mercurial, etc) to give you a list of changes files so you can manually go around re-uploading each of them, but this can take a long time on a large application.

Another option is re-uploading your entire site through FTP which is even more annoying, if not potentially dangerous to live servers as it can destroy file permissions, remove user-uploaded content, confuse cache systems and show programming errors throughout the site as files are deleted and replaced by the FTP client.

FTP clients tried making this easier for us by adding Syncronize features but they just compare dates so they are as useful as a chocolate teapot if you are trying to do careful deployments.

We clearly need another option, and thats where VCS deployments come in. In this case, Git.

I'm convinced, so how can I do it?

The best part is that if you are already working with Git on your local box then this is pretty damn easy to set up.

Step 1: SSH into your server

$ ssh [email protected]

Step 2: Install Git

$ sudo apt-get install git

Or use yum, aptitude, compile from source, etc.

Step 3: Setup your repo's

$ cd  /home/user/public_html
$ git init
$ git remote add origin [email protected]:philsturgeon/somerepo.git

This next command gets a little tricky if you already have your site running on this server. I have always used this method from the first deployment of Git managed sites, but you will probably need to delete any folders that will be managed by Git so they can be replaced. Of course be careful with backups and save any user uploaded content, but once that is done you wont have to worry about losing changes ever again.

$ git pull orgin master

Step 4: Deploy new changes

Once you have made some changes you will need to send them back to your main repository

$ git commit -a -m "Lazy commit of new stuff"
$ git push origin master

That will push everything to your repository, then SSH back into your live/testing server and pull the new changes.

$ git pull origin master

That will pull the changes from the main repository to the local repo on the live/testing site.

Last minute brainwave

I always SSH'ed in the pulled as that was how I used to do things when deploying with Subversion, but last night I had a sudden brainwave that cuts that step out completely.

You can push directly from your local box to the live website, or the testing server you are running Git on. On your local box you can simply add testing and live servers as another remote:

$ git remote add testing ssh://[email protected]/home/example/public_html
$ git remote add live ssh://[email protected]/home/example/public_html
$ git push origin master
$ git push testing master

And then when you have tested these changes had no screwy effects on your testing server:

$ git push live master

That means any time you make a change, you can commit it, push it back to the main codebase (GitHub, CodeBaseHQ, etc) then push it to the correct server(s). Sorted!

Update: After posting it came to my attention that directly pushing to a repository like this appears to work from the push end, but it wont actually update the files on the live server. To get this to happen you need to create a post-recieve hook.

$ ssh [email protected]
$ cd /home/example/public_html
$ vim .git/hooks/post-receive

The only thing in my post-recieve hook was the default example, so I deleted it and added this:


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

Save that with Escape then :wq and you need to permission the hook so it can be executed:

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

That's the hook completed.


The posibilities with Git are insane. These are two very useful ways to deploy your websites and i'm sure there are other methods. If you have an even better way to get your code from local, through testing and then to live with minumum fuss, please let me know!

Note: This article assumes you have SSH keys set up. You will need too add your local SSH public key to the Git repository server and add your live servers SSH key to the Git repository server for the live server to contact it. If you wish to deploy directly from local to live, then you can add your local SSH key to the live server but most servers by default will just ask for your user password.


Per Sikker Hansen


If you don't use github(you might want the code to be private and not want to pay for it) or another intermediary service, you can actually just push the data directly to the live/test server, assuming you have key-based ssh access.

On the server:
$ git branch pipeline

On the client:
$ git remote add production ssh://{domain/path}
$ git fetch production
$ git commit -a -m "Stuff was made, dawg"
$ git push production pipeline

And then on the server again:
$ git merge pipeline



Why do people think it's crazy to deploy from version control? It's the default model for capistrano, which is a tool primarily used by rails. We use the fast remote cache plugin ( successfully for our sites, some of which are about 2GB in site. Deployment is usually about 30 seconds or so for the larger sites.

There are some issues with a direct update for a busy site. You really need to stage the update, and then do a quick switchover to prevent some types of errors. Something capistrano handles well with a symlink.



Hi Phil,

I really like the thought of deploying websites in this way.

I'm probably going to use Mercurial myself for my EE projects, but I think the same principles apply.

One thing I noticed is that using this method, lots of files are visible if someone goes to your folders. I came across a .htaccess method to avoid this when reading this article:




An even better option, check out this post for a nicer .htaccess solution (as you use your main site's .htaccess file rather than put a new one in the .git directory:

Dave Holowiski


Thanks! There are some complicated scripts out there, but the simple post-receive hook does the job. I'm now using git to push PHP to my server :)
P.S. I put everything in a html subdirectory. On my server, the main directory is set to the html directory. That way, the .git folder is one folder up from the web server, and can't be accessed from the web server. No .htaccess required.



Is it possible to still use git to deploy codeigniter websites if I have my application and system folders moved one level up from the public root folder? the problem is that the front controller (index.php) and assets are located outside of the git repo.



Thank you

Chris Ostrowski


I was using Git aswell for quite a while, and things went decent... then I cam across SpringLoops.

I think every single developer needs to have a SpringLoops account. The services is unreal:

Zach Leatherman


Small typo:
git pull orgin master

Michishige Kaito


Actually, you probably don't want the live app to be a git work tree. It's a lot cleaner to just have a bare repo somewhere else, and use a post-receive hook to "archive" a fresh copy of the files to wherever you want them.



This is an excellent post. Thanks for share your informative information with all.[url=]iPhone[/url]



Appreciated to <a >Moncler Outlet</a> online! We organize been a worldwide business director in selling Moncler sale repayment for more than 5 years. As a masterful Moncler Online reseller, we have achieved spectacular celebrity in this hockey and organize served so profuse glad buyers. We have a bonny well-founded troupe who have been devoting themselves into reducing the costs by means of constantly looking for with greatest satisfaction and steadiest manufacturer. About the year 2008, we had expanded our frontier from <a >Moncler Spring</a> to a wider sort from Moncler Coats to <a >Moncler Online</a>. From us, people all over with the everybody dig buying property and give prodigal praises. <a >moncler loire coat</a> , luxury, put it on, and in a jiffy can subcontract out me charm to multiply, where can mature the target of the limelight, let you are another and echocardiography action. Don't Avoid <a >Moncler Coats</a> !
<a >moncler reynold jackets</a> with a hat takes on a trendy direction, compendious figure and slim-cut attire makes you more appealing and fashionable in the bustling street.
The team commented:"…the <a >Moncler Women Sale</a> were vital as withstanding the sick temperatures
during the tournament at 1,800m above multitude level.The finishing touches and lightness were outstanding…"
The pre-eminent of <a >moncler loire coat</a> was obviously from fortuitous,given the sporting and verifiable cosmos of both garments which are the customary situation of the first quilted <a >Moncler Women</a> to reach the apex of K2 with the Italian field trip in 1952
11 contributed sooner than providing quilted <a >Moncler Lucie price</a> on the thorough troupe,in the character of the amorous and
masterpiece Everest poser as a service to the men and the Badia model in place of the ladies.Both were personalised with the
coat of arms of the Maniaco ancestry which owns the Hotel De La Poste,embroidered in gold on both
strongbox and <a >Moncler Coats</a> .
<a >moncler angers coat</a> the Cortina Winter Polo On Snow struggle being contested,and as each year it featured the participation of Polo's most noted teams.
we are efficient <a >Moncler Autumn Sale</a> wholesaler,can yield all kinds of 2010 year costly attribute womens and mens moncler down coats.Dicount <a >Moncler Coats Price</a> winter jacket,<a >Moncler Jackets</a> winter clothing, <a >moncler reynold jackets</a> , <a >Moncler Women</a> , moncler jacket, <a >Moncler Coat Sale</a> , moncler apparel, <a >moncler moka down jacket</a> , winter garments, <a >Moncler Womens</a> ,interior decorator moncler feather coats supplier,<a >moncler reynold jackets</a> ,moncler feather clothing,<a >moncler reynold sale</a> , Moncler winter jacket, moncler, <a >Moncler Sweater sale</a> , moncler jacket,<a >Moncler Affton</a> ,moncler kids jacket ,Moncler women jackets - Mokacine, Bea, Bady ,<a >Moncler Womens</a> , Everest, Himalaya.

Laurence Cope


I am trying this out, but Git wont allow me to push to the live server, because its a git repository checked out from the master. I tried creating a bare repository as some sites suggest, but then all the git files are in the same directory as my software files, am sure that cant be right. So any suggestion on dealing with this issue would be great. Thanks

Laurence Cope


Seems on the live server (or where you want to push to) you have to use the following to create a bare repo: git init --bare

BUT do this in a sub-folder called .git that you create, else the git files git files get added into the directory your software will be in.

Then the post-receive file needs to have:



where path to folder is the directory to push to, the one that will contain the .git folder you created above.

This works for me!

Butch Ewing


This is exactly what I needed. Thanks!

Hannes Van De Vreken


I also had to do

git config receive.denyCurrentBranch ignore

according to: There's also something like a bare repository, but I didn't want to learn about all that when this one command fixes the problem.

Posting comments after three months has been disabled.