Recently I was challenged to integrate source code versioning and efficient
website deployment in a team that was not ready to switch from old-school FTP deployment.
I call it "lazy integration" because it is indeed full featured integration
while it doesn't force anyone in the team using GIT at all.
This post contains information on how I did it and aims to be a how-to reminder
for myself in case I will ever do this again. It works for me just fine but
I can't guarantee that by following this tutorial you won't harm your software
so use this tutorial on your own risk.
Let's take a brief look at what we're going to do and how things are going to work after
First, a bare repository is initialized out of production source code directory, some hooks
are being installed and repo can now be cloned to dev stations.
Pushing modifications to bare repository activates a hook
(pre-receive) that checks for any
local working directory (production source code) changes against HEAD (latest commit).
If no changes were found it just quits with no error and another hook
applies pushed commits to the working directory (production source code).
However, if any changes were detected they are submitted to a newly created commit and
hook quits with an error. At this point developer should bring that commit to
his cloned repo (by executing, let's say, PULL command) and PUSH once again.
What is so special in this flow? Well, it allows you to make changes directly on
PRODUCTION source code while still being able using GIT to track and deploy your
modifications. Some teams need just that but please make sure to read some of my thoughts
on that in the end of this post.
Let's get our hands dirty and try a real example.
Although I couldn't think of any software project that wouldn't fit this integration, I
expect you to make required adjustments for your specific scenario if you decided to apply this
integration to your project.
In our example we assume that we have a simple static website, it's
webroot path is
/var/htdocs/myproject on PRODUCTION server (also we assume that
you have SSH access to this server).
Initialize a GIT repository out of source code we have in
mkdir myproject.git && cd myproject.git
git init --bare
git --work-tree=../myproject add .
git --work-tree=../myproject commit -m'Initial commit'
Setup hooks. First, download
pre-receive hook as
make it executable:
wget http://bit.ly/19l9tpg -O pre-receive --no-check-certificate
chmod +x pre-receive
make it executable:
wget http://bit.ly/12XVJ57 -O post-receive --no-check-certificate
chmod +x post-receive
Now open both of the hooks in your editor of choice and make sure that the value of
represents the absolute or relative path (relatively to
of your source code directory.
You're ready to clone bare repository to your local dev station and PUSH from
Additionally, you could set some restrictions on your bare repository (I find
them reasonable on PRODUCTION bare repository):
git config receive.denyDeletes true
git config receive.denyNonFastForwards true
denyDeletes set to
true denies any attempts to delete a branch remotely.
denyNonFastForwards set to
true denies any attempts to delete/replace
existing commits remotely.
If updating working directory is not enough for your deployment needs I
suggest commiting a script which will do all is required and executing it
post-receive hook right after working tree update, like so:
GIT_WORK_TREE=$WORKTREE git checkout -f
if [ -e "$deploy_script" ]
In this example I'm executing
deploy.sh script which resides in the root of
my repository. Which means I can control my deployment right from my
local repo and any changes to script take place immediately. It's very
Although I believe that any source code deployment should be done via VCS like
GIT I know that there are not few programmers out there who're not ready to
waste their time learning VCS and they feel themselves uncomfortable with the
fact that any PRODUCTION update should go through a "long" deployment process.
So, even though I'm glad I could find a solution for teams with weak workflow,
I highly recommend changing the workflow rather than using this kind of solution.
And what kind of deployment strategy are you using in your projects?