Git deployment
continuous deployment
version control
web development
Git push

Deploy a project using Git push

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Deploying with git push usually means pushing code to a bare repository on a server and letting a Git hook update the live checkout. It is simple and effective for small systems, but it works safely only if the deployment script handles checkout, dependencies, and restart steps predictably.

How Git-Push Deployment Works

The standard layout has two repositories on the server:

  • a bare repository that receives pushes
  • a working directory that serves the application

When you push to the bare repository, a hook such as post-receive runs. That hook checks out the new revision into the live directory and optionally runs build or restart commands.

This is not a full CI or CD platform. It is a lightweight deployment mechanism built directly on top of Git.

Create the Bare Repository on the Server

On the server, create a bare repo that will receive pushes.

bash
mkdir -p /srv/git/myapp.git
cd /srv/git/myapp.git
git init --bare

A bare repository has no working tree. That is what makes it suitable as a push target.

Next, create the live application directory:

bash
mkdir -p /var/www/myapp

Add a post-receive Hook

Inside the bare repository, create hooks/post-receive:

bash
1#!/usr/bin/env bash
2set -e
3
4APP_DIR=/var/www/myapp
5BRANCH=refs/heads/main
6
7while read oldrev newrev ref
8 do
9  if [ "$ref" = "$BRANCH" ]; then
10    git --work-tree="$APP_DIR" --git-dir=/srv/git/myapp.git checkout -f main
11    cd "$APP_DIR"
12    npm ci
13    npm run build
14    systemctl restart myapp.service
15  fi
16 done

Then make it executable:

bash
chmod +x /srv/git/myapp.git/hooks/post-receive

This example assumes a Node.js app, but the same pattern works for other stacks. A Python deployment might run pip install -r requirements.txt, and a PHP deployment might run Composer.

Push from Your Local Repository

Add the server as a remote and push the branch you want to deploy.

bash
git remote add production [email protected]:/srv/git/myapp.git
git push production main

When the push completes, the hook runs on the server. If the script succeeds, the live directory updates to the pushed revision.

What a Good Hook Should Do

A production-worthy deployment hook should be deterministic. At minimum, it should:

  • deploy only a known branch
  • fail fast on command errors
  • install dependencies reproducibly
  • restart or reload the service safely
  • write logs so failures are diagnosable

It should not contain fragile ad hoc steps that depend on interactive shells, user-specific path state, or manually activated environments.

Limitations of Git-Push Deployment

This pattern is convenient, but it has limits. There is no approval gate, artifact versioning, rollback orchestration, or built-in secret management. If your system needs zero-downtime deploys, parallel environments, or compliance controls, a proper CI and deployment pipeline is usually the better tool.

Still, for personal projects, internal tools, or a single-server application, a Git hook deployment can be a pragmatic solution with very little infrastructure overhead.

Common Pitfalls

  • Pushing directly into a non-bare live repository can create branch and working-tree conflicts. Use a bare repository as the push target.
  • Letting the hook deploy every branch makes releases unpredictable. Restrict deployment to the branch you actually publish.
  • Running dependency installation without a reproducible lockfile can make deployments non-deterministic. Use npm ci, pinned requirements, or equivalent tooling.
  • Assuming the hook environment matches your interactive shell often causes path and runtime failures. Use explicit absolute paths in the script.
  • Skipping logs makes deployment failures hard to diagnose because the problem happens on the server side of the push. Capture stdout and stderr somewhere useful.

Summary

  • Git-push deployment usually means pushing to a bare repository with a post-receive hook.
  • The hook updates the live checkout and runs build or restart steps.
  • This is a practical deployment model for small systems and single-server apps.
  • The hook should be explicit, branch-aware, and deterministic.
  • For larger systems, CI/CD platforms provide better control and safety than a raw Git hook.

Course illustration
Course illustration

All Rights Reserved.