Deploying Websites With a Tiny Git Hook
By Ryan Florence, published 2010-07-27
Part of the issue Git Your Act and Deployment Together.
This method of deployment is similar to that discussed in Simple git deployment, but it takes out the logging-in-to-the-server-and-pulling step. It’s still a good idea to have a remote repository somewhere, but it isn’t involved here. Instead we just need a local repository and a repository on the web server.
Because git is “decentralized” we can push and pull to and from several different remote repositories. So why not simply add our web server as a remote repository and push to it when we want to update it? The trick is in using the post-receive hook.
Hooks?! Hooks are scripts that git will execute when awesome stuff happens, like after the repository receives a push. List the
.git/hooks directory to see what’s available:
$ ls example/.git/hooks applypatch-msg post-commit post-update pre-commit update commit-msg post-receive pre-applypatch pre-rebase
Alright, let’s do this:
Web Server: Login to your web server and create the repository
$ ssh email@example.com $ mkdir public_html/example.com $ cd public_html/example.com $ git init
Local Machine: Add the web server’s repository as a remote and name it
$ git remote add production ssh://firstname.lastname@example.org/~/public_html/example.com
Web Server: This is the tricky part. In step 5 we’re going to push our branch to the remote repository on the web server. The site won’t be updated after we push because the web server’s repository has a different commit, or set of files, in the working tree. No amount of pushing will force it to ‘reset’ to the most current commit (the one we’re going to push.) Therefore, we need to edit and enable the post-receive hook to reset the “HEAD” of the web server’s working tree.
It’s going to be in
example.com/.git/hooks and be named either
post-receive.sample. Open it up:
$ ssh email@example.com $ cd public_html/example.com $ vi .git/hooks/post-receive # or nano .git/hooks/post-receive.sample
There’ll be a lot of commented out lines, you can delete them all or leave them, doesn’t matter. Now paste this into it. (If editing files in the terminal isn’t your thing, just ftp the file.)
#!/bin/sh cd .. GIT_DIR='.git' umask 002 && git reset --hard
git reset --hard command updates the working tree with the newest commit in the branch. In other words, it updates the files in the folder to the most recent commit which happens to be the one that you just pushed. For a more robust post-receive script check this out, it’s what I actually use.
Web Server: Enable the hook. If your script was named post-receive.sample, rename it. Also, regardless of what it was named, you probably need to make it executable.
$ mv .git/hooks/post-receive.sample .git/hooks/post-receive $ chmod +x .git/hooks/post-receive
Local Machine: The hard part is over! Now make some changes on your local machine and push to the production remote repository. Like magic, your site updates itself, flippin’ sweet.
# make changes, commit, merge, etc. $ git push production master
Add more remotes for staging! You can push all over the place, just repeat the steps on different servers and you’re a git-deployment maniac.
$ git remote add stage ssh://firstname.lastname@example.org/~/stage.example.com $ git push stage master
Srsly d00d, no more FTP, okay?