Git for Server Deployments
Written by Ben Friedman, July 13th, 2016
Git is a fantastic tool for version control. Compared to alternatives we've found it to outperform consistently. Not only have we found it's performance to exceed our expectations, but we have found many nifty little tools within git. Particularly we are quite fond of running git as a server. There we can not only have our own centralized repository, but also our own managed automatic deployment mechanism. Updating a webserver is simply a push away.
Just to remain objective, there are similar benefits to other version control schemes. However we not only trust git from past performance, but also from it's history. Git was originally developed to handle the gargantuan code base of linux, after a fallout with BitKeeper. Not only was git built to handle the linux core, but it was built to do so efficiently. This meant moving as little as possible, and only when necessary. We find this reserved approach to version control is incredibly effective, particularly when managing large projects.
Git also has fanstatic client support, varying from the command line to wonderful GUIs. Assuming you're not a command line guru, support for git in the form of gui clients is in abundance. You can choose from well known products such as sourcetree and github desktop among others. This combination of great support and great functionality make git an ideal choice.
So, getting to the point of this article. How does git tie in with automatic server deployment? It turns out there's support for setting up bare repositories on a server, which most of you may be already aware of. Assuming you have your own server, you're practically ready to go. You'll be able to setup your own remote repository, allowing you and your team (and possibly more) to work collaboratively from your new base of operations.
This is only step 1 however, as this sets up what is referred to as a bare repository. A bare repository does not have a working directory, and thus no way to serve files! So the issue remains, how do we serve these files we push up to our server.
The answer lies in hooks, git hooks to be specific. A hook is a script called when a specific action occurs. In our case, we want to setup a hook for after we have recently received a push, or post-receive as this hook is called. An example hook might look something like this.
# your git hook in /my-gitserver.git/hooks/post-receive
git --work-tree=/var/www/mywebsite/html --git-dir=/my-gitserver.git checkout -f
To quickly summarize, the above sets up your working environment, aka your webserver, and then forcibly checks out the current repository from your git server. Now this is assuming you've set up /var/www/mywebsite/html as a git repository already, and that this is ready to serve content. When you run this all together you actually never touch your webserver contents directly. The idea here is that you only ever interact directly with your git server, which proxies your requests to your webserver.
Effectively this not only achieves what ftp does, but it also optimizes the traffic and caries all the benefits of git. If you make a mistake and you've pushed it up, you can always undo your change locally and push it up, undoing your changes as fast as you can 'git push'. Not only does this remove complexity in your deployment but it also provides a degree of integrity. Changes that have been pushed up to the server since you last pushed your own are tracked, and unless you've incorporated those changes yours will be blocked. No more accidentally overriding your coworker's last update!
This kind of a decentralized system also provides a high degree of redundancy, everyone who clones the repository has their own local copy of the server's contents. If something goes terribly wrong, you're almost guaranteed that someone will have the last working build to fix everything again.
Now this is a just a basic overview. We highly advise in your own implementations that you take extension measures to protect and control what is being sent to and from your server. An ACL or whitelist for users and permissions on actions is a good start, as well as providing some degree of validation on the code that's pushed. All this and more can be achieved with hooks, which can let you build an extensive authorization and validation system.
When you consider working with an automatic deployment scheme and can't quite seem to find something that suites you, consider going with your own git server. You just might find it just works better than what you're dealing with currently.
Questions? Corrections? Concerns? Contact us at firstname.lastname@example.org