Automated Deployments with Git: From Push to Production
Why Automate Deployments with Git?
Automated deployments mean that every time you push code to a specific branch (e.g., main) or create a tag, your application is automatically built, tested, and deployed to a server or cloud environment. This removes manual steps, reduces human error, and enables continuous delivery.
Core principle: Git becomes the single source of truth not only for code but also for the deployment process itself. Every deployment is repeatable and versioned.
Basic Git Deployment Strategies
1. Simple Git Push to Server
The most basic form: you have a remote repository on your production server, and you push directly to it. A Git hook (post-receive) then checks out the files and restarts services.
#!/bin/sh
git --work-tree=/var/www/myapp --git-dir=/repo.git checkout -f
systemctl restart myapp
2. CI/CD Pipeline Deployments
Modern approach: a CI server (GitHub Actions, GitLab CI, Jenkins) listens to Git events, runs tests, builds artifacts, and deploys to one or more environments (staging, production).
Key Deployment Environments
- Development – developer's local machine or shared dev branch.
- Staging / Pre-production – mirrors production for final testing.
- Production – live environment serving users.
Git branches often map to environments: feature/* → dev, develop → staging, main → production.
Deployment Methods Triggered by Git
A. Webhook-based deployment
A webhook is an HTTP callback triggered by a Git event (e.g., push). A small service on your server receives the webhook and runs a deployment script.
const express = require('express');
const { exec } = require('child_process');
const app = express();
app.post('/deploy', (req, res) => {
exec('./deploy.sh', (err, stdout) => {
console.log(stdout);
res.send('Deployed');
});
});
app.listen(4000);
B. CI/CD pipeline deployments (GitHub Actions example)
name: Deploy to production
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy to server
uses: appleboy/ssh-action@v1.0.0
with:
host: ${{ secrets.HOST }}
script: ./deploy-production.sh
C. GitOps style (pull-based)
In GitOps (e.g., with ArgoCD), a cluster-side operator continuously pulls from a Git repository and applies changes to the environment. This is the "pull" model: the target environment pulls updates from Git, instead of Git pushing to the environment.
Zero-Downtime Deployment Strategies
When you automate deployments, you also need to ensure your users don't experience downtime. Common patterns:
Blue-Green Deployments
Two identical environments: Blue (current live) and Green (new version). After deploying to Green and testing, switch the router to Green. Instant rollback by switching back.
Canary Deployments
Roll out the new version to a small subset of users (e.g., 5%). Monitor for errors, then gradually increase the percentage until 100%.
Rolling Updates
In a cluster (Kubernetes), instances are updated one by one, ensuring some capacity always remains available.
Using Git Tags for Deployment Triggers
Tags are excellent for marking releases. You can configure your CI to deploy to production only when a tag is pushed, not on every commit to main.
deploy_prod:
stage: deploy
script: ./deploy.sh
only:
- tags
Handling Database Migrations in Automated Deployments
Database changes are often the trickiest part. Common approaches:
- Immutable databases – create a new database for each deployment and migrate data (rare).
- Backward-compatible migrations – schema changes must work with both old and new code during the deployment (e.g., adding columns, not removing).
- Run migrations before code deployment – in CI, run migrations, then deploy code that uses the new schema.
stages:
- migrate
- deploy
migrate:
stage: migrate
script: npm run migrate
deploy:
stage: deploy
script: ./deploy.sh
Rollback Strategies
Automated deployments must have a rollback plan:
- Revert the Git commit – push a revert commit, let the pipeline deploy the old version.
- Re-deploy a previous tag – simply trigger deployment of an older Git tag.
- Blue-green switch – if using blue-green, switch back to the old environment.
Security Considerations
- Never store secrets in Git. Use CI secrets or external vaults (e.g., HashiCorp Vault).
- Use SSH keys with limited permissions for deployment.
- Consider using deploy tokens instead of personal credentials.
Real-World Example: Full Pipeline
- Developer pushes to
feature/xyz. CI runs tests. - PR merged to
main. CI runs tests again, builds Docker image, pushes to registry. - CI triggers a webhook on the production server, which pulls the new image and restarts services with zero downtime (rolling update).
- If something goes wrong, the previous Git tag is re-deployed.
Frequently Asked Questions
Use a service like Netlify or Vercel: connect your Git repository, and they automatically deploy every push to the production branch. For self-hosted, set up a post-receive hook on your server.
In your CI pipeline, run tests before the deployment stage. If tests fail, the pipeline stops and the deploy stage never runs. Branch protection rules can also prevent merging if CI fails.
Yes. In CI, you can check which files changed using git diff --name-only and conditionally run deployments for specific services. Tools like Turborepo or Nx help with this.
Continuous Delivery means every change is ready to be deployed to production, but a manual approval may be required. Continuous Deployment means every change that passes tests is automatically deployed to production.