Deployment with Git - Complete Guide
Published: September 25, 2024 | Reading time: 20 minutes
Git Deployment Overview
Git-based deployment strategies for automated releases:
Deployment Benefits
# Git Deployment Benefits
- Automated deployments
- Version control integration
- Rollback capabilities
- Environment consistency
- Team collaboration
- Deployment tracking
- Zero-downtime deployments
Git Hooks Deployment
Post-Receive Hook Setup
Git Hooks Deployment
# Git Hooks Deployment
# 1. Create post-receive hook
# On server: /var/repo/myapp.git/hooks/post-receive
#!/bin/bash
WORK_TREE=/var/www/myapp
GIT_DIR=/var/repo/myapp.git
# Deploy to production
git --work-tree=$WORK_TREE --git-dir=$GIT_DIR checkout -f
# Run build commands
cd $WORK_TREE
npm install --production
npm run build
# Restart services
sudo systemctl restart nginx
sudo systemctl restart myapp
# 2. Pre-receive hook validation
#!/bin/bash
# Validate deployment
while read oldrev newrev refname; do
if [[ $refname = "refs/heads/main" ]]; then
# Run tests
git --work-tree=/tmp/test --git-dir=/var/repo/myapp.git checkout -f $newrev
cd /tmp/test
npm test
if [ $? -ne 0 ]; then
echo "Tests failed, deployment rejected"
exit 1
fi
fi
done
# 3. Update hook for staging
#!/bin/bash
# Deploy to staging
WORK_TREE=/var/www/staging
GIT_DIR=/var/repo/myapp.git
git --work-tree=$WORK_TREE --git-dir=$GIT_DIR checkout -f staging
cd $WORK_TREE
npm install
npm run build:staging
# 4. Branch-based deployment
#!/bin/bash
while read oldrev newrev refname; do
branch=$(git rev-parse --symbolic --abbrev-ref $refname)
case $branch in
main)
deploy_production
;;
staging)
deploy_staging
;;
develop)
deploy_development
;;
esac
done
# 5. Environment-specific deployment
deploy_production() {
WORK_TREE=/var/www/production
GIT_DIR=/var/repo/myapp.git
git --work-tree=$WORK_TREE --git-dir=$GIT_DIR checkout -f main
cd $WORK_TREE
npm install --production
npm run build:production
# Health check
curl -f http://localhost:3000/health || exit 1
# Restart services
sudo systemctl restart myapp
}
deploy_staging() {
WORK_TREE=/var/www/staging
GIT_DIR=/var/repo/myapp.git
git --work-tree=$WORK_TREE --git-dir=$GIT_DIR checkout -f staging
cd $WORK_TREE
npm install
npm run build:staging
}
CI/CD Integration
GitHub Actions Deployment
CI/CD Deployment
# GitHub Actions Deployment
# .github/workflows/deploy.yml
name: Deploy to Production
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Build application
run: npm run build
deploy:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: npm ci
- name: Build application
run: npm run build
- name: Deploy to server
uses: appleboy/ssh-action@v0.1.5
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.SSH_KEY }}
script: |
cd /var/www/myapp
git pull origin main
npm install --production
npm run build
sudo systemctl restart myapp
# 2. Multi-environment deployment
name: Multi-Environment Deployment
on:
push:
branches: [ main, staging, develop ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Determine environment
id: env
run: |
if [[ $GITHUB_REF == 'refs/heads/main' ]]; then
echo "environment=production" >> $GITHUB_OUTPUT
elif [[ $GITHUB_REF == 'refs/heads/staging' ]]; then
echo "environment=staging" >> $GITHUB_OUTPUT
else
echo "environment=development" >> $GITHUB_OUTPUT
fi
- name: Deploy to ${{ steps.env.outputs.environment }}
uses: appleboy/ssh-action@v0.1.5
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.SSH_KEY }}
script: |
cd /var/www/${{ steps.env.outputs.environment }}
git pull origin ${{ github.ref_name }}
npm install
npm run build:${{ steps.env.outputs.environment }}
sudo systemctl restart myapp-${{ steps.env.outputs.environment }}
Deployment Strategies
Advanced Deployment Patterns
Deployment Strategies
# Deployment Strategies
# 1. Blue-Green Deployment
#!/bin/bash
# Blue-Green deployment script
CURRENT_COLOR=$(cat /var/www/current_color)
if [ "$CURRENT_COLOR" = "blue" ]; then
NEW_COLOR="green"
OLD_COLOR="blue"
else
NEW_COLOR="blue"
OLD_COLOR="green"
fi
# Deploy to new environment
git --work-tree=/var/www/$NEW_COLOR --git-dir=/var/repo/myapp.git checkout -f main
cd /var/www/$NEW_COLOR
npm install --production
npm run build
# Health check
curl -f http://localhost:3001/health || exit 1
# Switch traffic
sudo ln -sf /var/www/$NEW_COLOR /var/www/current
echo $NEW_COLOR > /var/www/current_color
# Restart services
sudo systemctl restart nginx
sudo systemctl restart myapp
# 2. Rolling Deployment
#!/bin/bash
# Rolling deployment script
SERVERS=("server1" "server2" "server3")
for server in "${SERVERS[@]}"; do
echo "Deploying to $server..."
ssh $server "cd /var/www/myapp && git pull origin main"
ssh $server "cd /var/www/myapp && npm install --production"
ssh $server "cd /var/www/myapp && npm run build"
ssh $server "sudo systemctl restart myapp"
# Health check
ssh $server "curl -f http://localhost:3000/health" || exit 1
echo "Deployment to $server completed"
done
# 3. Canary Deployment
#!/bin/bash
# Canary deployment script
# Deploy to canary server
git --work-tree=/var/www/canary --git-dir=/var/repo/myapp.git checkout -f main
cd /var/www/canary
npm install --production
npm run build
# Route 10% traffic to canary
sudo nginx -s reload
# Monitor canary for 10 minutes
sleep 600
# Check metrics
CANARY_ERROR_RATE=$(curl -s http://localhost:3001/metrics | grep error_rate)
if [ "$CANARY_ERROR_RATE" -lt "0.01" ]; then
# Deploy to production
deploy_production
else
# Rollback canary
sudo nginx -s reload
exit 1
fi
# 4. Feature Flag Deployment
#!/bin/bash
# Feature flag deployment
# Deploy with feature flags
git --work-tree=/var/www/myapp --git-dir=/var/repo/myapp.git checkout -f main
cd /var/www/myapp
npm install --production
# Set feature flags
export FEATURE_NEW_UI=true
export FEATURE_BETA_API=false
npm run build
sudo systemctl restart myapp
# 5. Database Migration Deployment
#!/bin/bash
# Database migration deployment
# Backup database
mysqldump -u root -p myapp > /backup/myapp_$(date +%Y%m%d_%H%M%S).sql
# Run migrations
cd /var/www/myapp
npm run migrate:up
# Deploy application
git --work-tree=/var/www/myapp --git-dir=/var/repo/myapp.git checkout -f main
npm install --production
npm run build
# Health check
curl -f http://localhost:3000/health || {
# Rollback migration
npm run migrate:down
exit 1
}
sudo systemctl restart myapp
Deployment Best Practices
Production Guidelines
Deployment Best Practices
- Automate all deployments
- Use environment-specific configs
- Implement health checks
- Monitor deployment metrics
- Have rollback procedures
- Test in staging first
- Use feature flags
Common Mistakes
- Manual deployments
- No health checks
- Missing rollback plans
- Deploying to production directly
- Not monitoring deployments
- Ignoring environment differences
- Poor error handling
Summary
Git-based deployment involves several key components:
- Git Hooks: Automated deployment triggers
- CI/CD Integration: GitHub Actions and automation
- Deployment Strategies: Blue-green, rolling, canary deployments
- Best Practices: Guidelines and common mistakes
Need More Help?
Struggling with Git deployment setup or need help implementing automated deployment strategies? Our deployment experts can help you set up robust deployment pipelines.
Get Deployment Help