This is mostly a personal note on how to setup a workflow with my Web Development (PHP/MySQL & Docker based) projects. Usually, with pretty much any project, the workflow goes as follows:

Figure: My workflow prior to this article
To host my own repositories of codes per project, I actually use GOGS which is short for Go Git Service – it’s written of course, in google Go, and is essentially a self-hosted Github clone. It’s by one of the devs from the Gitlab team, and it’s far more lightweight and easier to use in a personal scope, than Gitlab (Gitlab is still wonderful, but I think it’s better suited to teams of 2 or more people).
Git hooks are amazing!
The above workflow diagram though, is missing one really critical stage – getting the code to production – a.k.a. deployment. Typically on any deployment, after the above workflow, I’d either remote in, or set up a cron job to pull from master. There’s some problems with this method of doing things:
- I’m doing a git pull which is based on merges, and can really cause some shit if there’s a conflict (there shouldn’t be, but just in case)
- I’m remoting into the server each time I have to pull for some commits, this takes up time. I’m a serial commit/push-as-save person
- It’s completely against the ethos of a developer. If I’m doing something repeatedly, I should find a way to automate it!
So, enter stage – Git hooks. Git hooks are amazing! They’re actually natively supported by Git (powered by Git) and I only really just started learning about using them. I vaguely recall encountering them earlier in my growth as a dev, but I must’ve shelved it at some point and given up trying to learn hooks (probably around the same time I cracked it at Drone CI, and Jenkins CI/CD).
Anyway, the overall concept of using a Git Hook is that I reach the final stage of the workflow I drew at the start of this article Git push to remote repository – the idea is that the Git repo then registers this push in something called a post-receive
hook. It then performs some functions and essentialy plonks a pull of the latest code of my repo, into the production environment.
At first, I started off with something super simple, from my jtiong.com (this website!) repository as an example:
#!/bin/sh
ssh [email protected] 'cd /var/www/jtiong.com && git fetch && git reset --hard origin/master'
Unfortunately, this didn’t seem to work. I kept getting remote: Gogs internal error
messages, and figured out it was something to do with my SSH keys not working in the authorized_keys and known_hosts files of the docker container to server shell and vice versa. After a lot of Google-fu and tinkering around, I eventually came up with the following which worked (note, it’s been edited to be a generic solution).
#!/bin/bash
ssh -o StrictHostKeyChecking=no [email protected] -p 22 -i /home/git/.ssh/id_rsa 'cd /project/folder/path && git fetch && git reset --hard origin/master'
It’s not entirely necessary, but I used the -p
and -i
options to specify both the SSH port and identity file used with the SSH connection (just for greater control, you should be able to remove them, your results may vary). The key section of the above command that I want to highlight is the -o StrictHostKeyChecking=no
option that I’ve set. This got rid of any Host Key issues between the docker container and the host server for me. So if you’re encountering issues with your Host Key Verification
or similar, this might fix your problems!
With the git command now, I used git fetch && git reset --hard origin/master
instead of just doing a git pull
. Why? Because git pull uses merge methods and can result in some conflicts with code, and issues that are just messy and a bad experience to untangle. Using git reset, moves the code’s pointer to a different commit without merging anything. It just overwrites it, making it slightly safer for deployment!
But of course… Why do things in just a simple way? This particular hook configuration is great for something like my personal site where I don’t mind if I’m pushing breaking bugs to production (within reason). However, when I’m doing work for clients, I need to be a little bit more careful – and I use a more typical production, staging, development branching method with my Gitflow.
Here’s what I use now:
And wonderfully – this lets me have separate branches, as required and updates the appropriate (sub)domain as needed! The wonder of Git Hooks has now streamlined how I develop projects, and deploy them in a much more pain-free manner! And so I dramatically take another step in my journey and growth as a developer haha 😛