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.
A bare repository has no working tree. That is what makes it suitable as a push target.
Next, create the live application directory:
Add a post-receive Hook
Inside the bare repository, create hooks/post-receive:
Then make it executable:
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.
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-receivehook. - 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.

