Tutorials

Automating Website Deployments with Git: A Practical Guide

Muhammad SaadApril 17, 20266 min read
Automating Website Deployments with Git: A Practical Guide

Manually uploading files via FTP every time you make a change? That's not just tedious — it's risky. One wrong file, one forgotten upload, and your site breaks. Automated deployment eliminates these problems entirely. Push your code to Git, and your site updates itself.

Here's how to set it up, from simple Git hooks to full CI/CD pipelines.

Why Automate Deployments?

Manual deployment has real costs:

  • Human error: Forgetting to upload a file or uploading the wrong version
  • Time waste: FTP transfers, SSH sessions, running build commands by hand
  • No rollback: When something breaks, reverting is painful
  • Inconsistency: "It works on my machine" becomes a daily headache

Automated deployment solves all of these. Your deployment process becomes reproducible, fast, and reversible.

Method 1: Git Hooks (Simplest)

If your site runs on a VPS, Git hooks are the easiest way to deploy automatically.

How It Works

  1. You push code to a bare Git repository on your server
  2. A post-receive hook runs automatically
  3. The hook copies your code to the web directory

Setup

On your server, create a bare repository:

mkdir -p /home/deploy/mysite.git
cd /home/deploy/mysite.git
git init --bare

Create the post-receive hook:

nano hooks/post-receive

Add this script:

#!/bin/bash
TARGET="/var/www/mysite"
GIT_DIR="/home/deploy/mysite.git"
BRANCH="main"

while read oldrev newrev ref
do
    if [ "$ref" = "refs/heads/$BRANCH" ]; then
        echo "Deploying $BRANCH to $TARGET..."
        git --work-tree=$TARGET --git-dir=$GIT_DIR checkout -f $BRANCH

        # Run build steps if needed
        cd $TARGET
        npm install --production 2>&1
        npm run build 2>&1

        # Restart application
        pm2 restart mysite 2>&1

        echo "Deployment complete!"
    fi
done

Make it executable:

chmod +x hooks/post-receive

On your local machine, add the server as a remote:

git remote add production deploy@yourserver:/home/deploy/mysite.git

Now deploy with:

git push production main

That's it. Push and your site updates.

Pros and Cons

Pros: Simple, no third-party services, instant deployment

Cons: No build environment isolation, limited error handling, single server only

Method 2: GitHub Actions (Recommended)

GitHub Actions gives you a proper CI/CD pipeline — build, test, and deploy automatically when you push to GitHub.

Basic Deployment Workflow

Create .github/workflows/deploy.yml in your repository:

name: Deploy to Production

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Run tests
        run: npm test

      - name: Build
        run: npm run build

      - name: Deploy to server
        uses: appleboy/ssh-action@v1
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            cd /var/www/mysite
            git pull origin main
            npm install --production
            npm run build
            pm2 restart mysite

Setting Up Secrets

In your GitHub repository:

  1. Go to Settings → Secrets and variables → Actions
  2. Add these secrets:
    • SERVER_HOST: Your server IP
    • SERVER_USER: SSH username
    • SSH_PRIVATE_KEY: Your private SSH key

WordPress Deployment

For WordPress sites, deploy theme or plugin changes:

name: Deploy WordPress Theme

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Deploy via rsync
        uses: burnett01/rsync-deployments@6.0.0
        with:
          switches: -avzr --delete --exclude='.git'
          path: wp-content/themes/mytheme/
          remote_path: /var/www/html/wp-content/themes/mytheme/
          remote_host: ${{ secrets.SERVER_HOST }}
          remote_user: ${{ secrets.SERVER_USER }}
          remote_key: ${{ secrets.SSH_PRIVATE_KEY }}

Pros and Cons

Pros: Free for public repos (2,000 minutes/month for private), runs tests before deploying, great ecosystem of actions

Cons: Requires GitHub, slight delay (1-3 minutes for pipeline to run)

Method 3: Simple Deploy Script

Sometimes you don't need a full pipeline — just a script that deploys reliably.

deploy.sh

#!/bin/bash
set -e  # Exit on any error

SERVER="deploy@yourserver.com"
REMOTE_DIR="/var/www/mysite"
BRANCH="main"

echo "🚀 Starting deployment..."

# Ensure we're on the right branch
CURRENT_BRANCH=$(git branch --show-current)
if [ "$CURRENT_BRANCH" != "$BRANCH" ]; then
    echo "❌ Not on $BRANCH branch. Aborting."
    exit 1
fi

# Check for uncommitted changes
if [ -n "$(git status --porcelain)" ]; then
    echo "❌ Uncommitted changes found. Commit first."
    exit 1
fi

# Build locally
echo "📦 Building..."
npm ci
npm run build

# Deploy
echo "📤 Deploying to server..."
rsync -avz --delete \
    --exclude='.git' \
    --exclude='node_modules' \
    --exclude='.env' \
    ./dist/ $SERVER:$REMOTE_DIR/

# Restart remote application
echo "🔄 Restarting application..."
ssh $SERVER "cd $REMOTE_DIR && pm2 restart mysite"

echo "✅ Deployment complete!"

Run it:

chmod +x deploy.sh
./deploy.sh

Zero-Downtime Deployments

For production sites where every second matters, deploy without taking the site offline:

#!/bin/bash
DEPLOY_DIR="/var/www/mysite"
RELEASE_DIR="/var/www/releases/$(date +%Y%m%d%H%M%S)"

# Deploy to a new release directory
mkdir -p $RELEASE_DIR
git --work-tree=$RELEASE_DIR checkout -f main

# Install and build
cd $RELEASE_DIR
npm install --production
npm run build

# Swap the symlink (atomic operation)
ln -sfn $RELEASE_DIR $DEPLOY_DIR

# Restart app
pm2 restart mysite

# Keep only last 5 releases
ls -dt /var/www/releases/*/ | tail -n +6 | xargs rm -rf

The symlink swap is atomic — visitors never see a half-deployed state.

Rollback Strategy

Every deployment system needs a way to undo mistakes. If using the release directory approach above:

# List available releases
ls -lt /var/www/releases/

# Rollback to previous release
ln -sfn /var/www/releases/20260228143022 /var/www/mysite
pm2 restart mysite

With Git:

# Revert to previous commit
git revert HEAD
git push origin main
# Automated pipeline redeploys the reverted code

Best Practices

  1. Never deploy directly to production without testing. Even a simple npm test catches obvious issues.

  2. Use environment variables for configuration. Never commit secrets, API keys, or database passwords.

  3. Deploy frequently in small increments. Small changes are easier to debug when something breaks.

  4. Monitor after deployment. Watch your error logs and uptime monitoring for the first 15 minutes after each deploy.

  5. Keep deployment fast. If your pipeline takes more than 5 minutes, optimize it. Slow deployments discourage frequent releases.

  6. Document your process. Write down how to deploy manually as a fallback. Automation fails sometimes.

Choose Your Approach

Just starting out?
├── Static site → Git hooks or rsync script
├── WordPress → rsync with GitHub Actions
├── Node.js app → GitHub Actions with PM2
└── Complex app → Full CI/CD pipeline

Growing team?
├── GitHub Actions (most teams)
├── GitLab CI (if using GitLab)
└── Jenkins (enterprise, self-hosted)

Deploy with Confidence

Automated deployment removes the stress and risk from putting your code live. Start simple — even a basic deploy script is better than manual FTP uploads — and evolve your process as your project grows.

At DeployBase, we support Git-based deployments out of the box. Our VPS plans come with SSH access, Git pre-installed, and the flexibility to set up any deployment workflow you prefer. Whether you're using Git hooks, GitHub Actions, or custom scripts, DeployBase gives you the infrastructure to deploy fast and reliably.

Get started with DeployBase → — hosting built for developers who ship.

Share this article

Muhammad Saad

Muhammad Saad

DeployBase Team

Ready to Get Started?

Join thousands of developers who trust DeployBase for their hosting needs.