So you’ve got a local git repository, and you want to deploy it to your own server. Maybe the repo is kept in GitHub, maybe not. Maybe your server is on DigitalOcean, or AWS, or in your basement. It doesn’t much matter.
The goal: when you run
git push, deploy the latest
master branch to the server. Let’s set it up.
How to Deploy a Git Repo
There are lots of ways to do this. On one end of the spectrum is copying files with
rsync or even FTP. On the other, more modern side, there’s full-blown continuous deployment systems like CircleCI.
This approach sits in the middle. You don’t need to set up or sign up for any services. This is 100% DIY. But it’s using git to do the deploy, so it’s a step above just copying files, because you’re deploying a specific commit (not just whatever files are laying around).
Here’s a rough diagram of what will happen with this setup:
On the server…
- We’ll create a “bare” git repository, to receive the deployed files (
- The bare repo will not have our actual project files, which isn’t terribly useful, so…
post-receivehook in there will check out the files into a “worktree” (a separate folder,
deployed_projectin the diagram)
- We can customize the
post-receivehook to do extra stuff too: install packages, run a build, restart a service, etc.
On your computer…
- Add the server as a “remote” to the git repo, using the path to the bare repo on the server
git pushand off it goes
Step by Step
1. Create the Bare Repo
Create a bare git repo on the server. Doesn’t matter where this goes, as long as you have permission to write to it. Your home directory would work fine. (e.g.
/home/you/your_project.git). The “.git” at the end is not required, but it’s a good reminder that this directory is not a regular project.
ssh you@your-server git init --bare /path/to/bare_project.git
ls /path/to/bare_project.git and see what it contains)
2. Create the post-receive Hook
Create the file
/path/to/bare_project.git/hooks/post-receive and add this:
#!/bin/sh # Check out the files git --work-tree=/var/www/deployed_project --git-dir=/path/to/bare_project.git checkout -f
This file needs to be executable so use
chmod to make that happen. (don’t skip this step!)
chmod +x /path/to/bare_project.git/hooks/post-receive
3. Configure your local repo to push to the server
We’ll add a “remote” to your local repo. A remote is an endpoint that git can push to. The address can look like a URL (
ssh://you@your-server/path/to/files) or it can be in the SSH format (
When I set this up for myself, I put the bare repo in my home directory, so the path was
me@my-server:my-project.git (no absolute path needed, since it’s right in the home directory).
Run this within your own local repo:
git remote add live 'you@your-server:/path/to/bare_project.git' git push --set-upstream live master
The name “live” can be whatever you want (“prod”, “production”, “deploy”, etc.).
The second command is what binds your
master branch to the
live remote, so when you run
git push, git knows where to push.
(You can verify that the remote was added correctly by running
git remote -v)
Try it Out!
git push inside your local repo. Assuming everything is working right, you should see git push up the files, and it shouldn’t print any errors.
Then, log in to your server and make sure the project files were checked out in the
/var/www/deployed_project location (wherever you put them).
Run Tasks After Deploy with Git
Your project is deployed now. Awesome!
But maybe there’s more you wanted to do, like restart a server, or run
npm install to sync up packages, or some other thing.
post-receive script you already have is the perfect place to do this.
Just beware that the “working directory” that the script runs in might not be where you think. Be sure to
cd to the right place first. And the
PATH might not be what it would normally be when you’re logged in, so referring to executables by their full path can be a good idea too.
Here’s an example of running
npm install and restarting a service after each deploy:
#!/bin/sh # Check out the files git --work-tree=/var/www/deployed_project --git-dir=/path/to/bare_project.git checkout -f # Install packages cd /var/www/deployed_project npm install # Restart the web server # (requires sudoers to allow this command without a password) sudo /bin/systemctl restart my-project.service
If the npm command fails, login and run
which npm, then use that full path in the command, like
Run sudo commands from a post-receive hook
sudo command fails with an error about “no interactive terminal” or some such, that’s because it’s trying to ask for a password. That won’t work. But you can add a rule to the sudoers file that will let you run just this one command without a password.
Log in to your server over SSH and run
sudo visudo. On my Ubuntu 18.04 system, I have a line that looks like:
%sudo ALL=(ALL:ALL) ALL
That allows everyone in the
sudo group to use
sudo with a password. Add another line below it to make an exception for this command:
%sudo ALL=(ALL:ALL) ALL %sudo ALL=(ALL:ALL) NOPASSWD: /bin/systemctl restart my-project.service
The command there must exactly match the one in your
post-receive script. Save, quit, and give it another shot.
Learning React can be a struggle — so many libraries and tools!
My advice? Ignore all of them :)
For a step-by-step approach, check out my Pure React workshop.
Learn to think in React
- 90+ screencast lessons
- Full transcripts and closed captions
- All the code from the lessons
- Developer interviews
Dave Ceddia’s Pure React is a work of enormous clarity and depth. Hats off. I'm a React trainer in London and would thoroughly recommend this to all front end devs wanting to upskill or consolidate.