Git code version control deployment

Automated Deployment with Git on VPS – No More FTP

June 2026 · 7 min read

Deploying via FTP or manually copying files every time wastes time and risks errors. Use a Git bare repository on your VPS combined with a post-receive hook to let git push automatically deploy your code in one command.


The Concept

Step 1: Set Up on Your VPS

# Create a deploy user (if you don't have one already)
adduser deploy
usermod -aG www-data deploy

# Create the bare repository
mkdir -p /var/repo/mysite.git
cd /var/repo/mysite.git
git init --bare

Step 2: Write the post-receive Hook

nano /var/repo/mysite.git/hooks/post-receive
#!/bin/bash
TARGET="/var/www/html/mysite"
GIT_DIR="/var/repo/mysite.git"
BRANCH="main"

while read oldrev newrev ref; do
  if [[ $ref = refs/heads/$BRANCH ]]; then
    echo "Deploying $BRANCH..."
    git --work-tree=$TARGET --git-dir=$GIT_DIR checkout -f $BRANCH
    echo "Done."
  fi
done
chmod +x /var/repo/mysite.git/hooks/post-receive

Step 3: Set Up Permissions

mkdir -p /var/www/html/mysite
chown -R deploy:www-data /var/www/html/mysite
chown -R deploy:deploy /var/repo/mysite.git

Step 4: Add Remote on Your Local Machine

# In your project directory on your local machine
git remote add vps deploy@your-vps-ip:/var/repo/mysite.git

# First deployment
git push vps main

Add a Hook to Restart Services

If your application needs to restart after deployment, add this to your hook:

# Append to post-receive after the checkout command
systemctl restart php8.3-fpm
# Or for Node.js:
pm2 restart myapp
SSH Key: Copy your local machine's public key to /home/deploy/.ssh/authorized_keys on the VPS so you don't have to type your password every time you push.

Test the Workflow

# On your local machine
echo "test" >> README.md
git add README.md
git commit -m "test deploy"
git push vps main
# Watch for the hook output and verify files are copied to the web root

Summary

After setting up once, deployment becomes as simple as typing git push vps main, reducing the risk of errors from manual file copying and providing a complete Git history as an audit trail at all times.

Verify Deployment is Working Correctly

# Check the output in your terminal after git push
git push vps main
# You should see: "Deploying main..." and "Done."

# Verify files in the web root on your VPS
ls -la /var/www/html/mysite/

# Test that the website responds
curl -I https://example.com
Add logging to the hook: Insert exec > /tmp/deploy.log 2>&1 at the first line of post-receive for easier debugging. Then view it with tail -f /tmp/deploy.log

Common Issues & Troubleshooting

Error: "Permission denied (publickey)" when running git push

Your SSH public key hasn't been added to the VPS yet. Check and add it:

# On your local machine: copy your public key
cat ~/.ssh/id_rsa.pub

# On the VPS: add it to the deploy user's authorized_keys
mkdir -p /home/deploy/.ssh
nano /home/deploy/.ssh/authorized_keys
chmod 700 /home/deploy/.ssh
chmod 600 /home/deploy/.ssh/authorized_keys
chown -R deploy:deploy /home/deploy/.ssh

Error: "remote: bash: post-receive: Permission denied"

You forgot to make the hook file executable:

chmod +x /var/repo/mysite.git/hooks/post-receive
ls -la /var/repo/mysite.git/hooks/post-receive
# Should show: -rwxr-xr-x

Error: Files are pushed but don't appear in the web root

The branch name in the hook might not match. The hook uses main but you're pushing to master:

# Check your current branch
git branch

# If it's named master, rename it
git branch -m master main
git push vps main

Error: Hook runs but files don't get overwritten

Check that the deploy user has write permissions:

ls -la /var/www/html/ | grep mysite
chown -R deploy:www-data /var/www/html/mysite

Error: "error: src refspec main does not match any"

You haven't committed anything on your local machine yet. You must have at least one commit before you can push:

git add .
git commit -m "initial commit"
git push vps main

Frequently Asked Questions

Can I deploy multiple projects on the same VPS?

Yes. Create separate bare repositories for each project, for example /var/repo/site1.git and /var/repo/site2.git. Each one has its own hook and target directory.

Can I roll back to a previous version?

Yes. Git keeps your full history:

# Revert and push again
git revert HEAD
git push vps main

How do I manage environment variables?

Don't commit the .env file to your repository. Instead, create .env directly on the VPS by hand, and add it to .gitignore.

Can I use GitHub Actions instead of a bare repository?

Yes, but a bare repository approach works on its own without relying on third-party services and pushes directly to your VPS in one step without going through the cloud.