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.

# On the server (bare repository) – .git/hooks/post-receive
#!/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.

# Example using a simple Node.js webhook listener
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)

# .github/workflows/deploy.yml
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.

# GitLab CI: deploy only for tags
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.
# Example: run migrations in CI before deploying
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

  1. Developer pushes to feature/xyz. CI runs tests.
  2. PR merged to main. CI runs tests again, builds Docker image, pushes to registry.
  3. CI triggers a webhook on the production server, which pulls the new image and restarts services with zero downtime (rolling update).
  4. If something goes wrong, the previous Git tag is re-deployed.
Which deployment strategy uses two identical environments and switches traffic instantly?
  • Blue-green deployment
  • Canary deployment
  • Rolling update
  • Git push hook

Frequently Asked Questions

What's the simplest way to auto-deploy a static site with Git?

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.

How do I prevent automatic deployment if tests fail?

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.

Can I deploy only specific folders from a monorepo?

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.

What is the difference between continuous delivery and continuous deployment?

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.

Previous: Versioning Strategies Next: Monorepo Automation