Publ: Continuous deployment with git

Last updated:

This is the approach I use for managing my site content on my main website.

Initial setup

On your webserver, create a private git repository wherever you want it, for example, $HOME/sitefiles/; here is an example of how to do so (after logging into your server with ssh):

mkdir -p $HOME/sitefiles
git init --bare $HOME/sitefiles/
git clone $HOME/sitefiles/

Now you’ll have a bare repository in sitefiles/ and an application directory in

Back on your desktop (or wherever you’re developing your site), configure the bare repository as your publishing remote; for example:

git remote add publish username@servername:sitefiles/

Now back on the server, you need two git hooks. First, the post-update hook on the bare repo, e.g. $HOME/sitefiles/


echo "Deploying new site content..."

cd $HOME/
unset GIT_DIR
git checkout . &&  git pull

Next, the post-merge hook on the deployment repo, e.g. $HOME/


if git diff --name-only HEAD@{1} | grep -q Pipfile.lock ; then
    echo "Pipfile.lock changed; redeploying"
    cd "$GIT_DIR/.."
    pipenv install

echo "Restarting web services"
killall -HUP gunicorn

Deploying changes

Now, when you push new content to the publish remote, it will go to the bare repo, which will then tell the deployment repo to pull the latest changes. After these changes are deployed, it will update whatever packages changed in your Pipfile, and then restart your gunicorn processes. (Yes, all of them. If you have multiple gunicorn sites you’ll probably want to do something to track the process ID on a per-site basis.)