Update on 20/06/2013
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 we finish.
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 (post-receive) 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 myproject
directory:
cd /var/htdocs
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
/var/htdocs/myproject.git/hooks/pre-receive
and
make it executable:
cd /var/htdocs/myproject.git/hooks
wget http://bit.ly/19l9tpg -O pre-receive --no-check-certificate
chmod +x pre-receive
Next, download
post-receive hook
as /var/htdocs/myproject.git/hooks/post-receive
and
make it executable:
cd /var/htdocs/myproject.git/hooks
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 WORKTREE
variable
represents the absolute or relative path (relatively to /var/htdocs/myproject.git/
)
of your source code directory.
You're ready to clone bare repository to your local dev station and PUSH from it.
Additionally, you could set some restrictions on your bare repository (I find them reasonable on PRODUCTION bare repository):
cd /var/htdocs/myproject.git
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
in post-receive
hook right after working tree update, like so:
# update the working tree
GIT_WORK_TREE=$WORKTREE git checkout -f
# run custom deploy script
deploy_script="$WORKTREE/deploy.sh"
if [ -e "$deploy_script" ]
then
. $deploy_script
fi
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
powerful.
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?
Hi, I'm Sergey, 30yo, father of 2, currently based in Tel Aviv, Israel.
I'm mostly passionate about #music, #programming, #sport, #ui, #ux ...in alphabetical order :)
Read more about me in my Résumé