Tutorial

How To Set Up Automatic Deployment with Git with a VPS

Published on August 9, 2013
author

Caio Vaccaro

How To Set Up Automatic Deployment with Git with a VPS

Introduction

For an introduction to Git and how to install, please refer to the introduction tutorial.

This article will teach you how to use Git when you want to deploy your application. While there are many ways to use Git to deploy our application, this tutorial will focus on the one that is most straightforward. I assume you already know how to create and use a repository on your local machine. If not, please refer to this tutorial.

When you use Git, the workflow generally is toward version control only. You have a local repository where you work and a remote repository where you keep everything in sync and can work with a team and different machines. But you can also use Git to move your application to production.

Server Setup

Our fictitious workspace:

Your server live directory: /var/www/domain.com

Your server repository: /var/repo/site.git

What should we do if we want to push to site.git and at the same time make all the content available at /var/www/domain.com?

Creating Our Repository

Login to your VPS from command line and type the following:

cd /var
mkdir repo && cd repo
mkdir site.git && cd site.git
git init --bare

--bare means that our folder will have no source files, just the version control.

Hooks

Git repositories have a folder called 'hooks'. This folder contains some sample files for possible actions that you can hook and perform custom actions set by you.

Git documentation define three possible server hooks: 'pre-receive', 'post-receive' and 'update'. 'Pre-receive' is executed as soon as the server receives a 'push', 'update' is similar but it executes once for each branch, and 'post-receive' is executed when a 'push' is completely finished and it's the one we are interested in.

In our repository if you type:

ls

You will see a few files and folders, including the 'hooks' folder. So let's go to 'hooks' folder:

cd hooks

Now, create the file 'post-receive' by typing:

cat > post-receive

When you execute this command, you will have a blank line indicating that everything you type will be saved to this file. So let's type:

#!/bin/sh
git --work-tree=/var/www/domain.com --git-dir=/var/repo/site.git checkout -f

When you finish typing, press 'control-d' to save. In order to execute the file, we need to set the proper permissions using:

chmod +x post-receive

You can see on the documentation that 'git-dir' is the path to the repository. With 'work-tree', you can define a different path to where your files will actually be transferred to.

The 'post-receive' file will be looked into every time a push is completed and it's saying that your files need to be in /var/www/domain.com.

Local Machine

Let's create our local repository. You should change the path and name to whichever you choose. If you are on a VPS, just type:

exit

And create your repo:

cd /my/workspace
mkdir project && cd project
git init

Then we need to configure the remote path of our repository. Tell Git to add a remote called 'live':

git remote add live ssh://user@mydomain.com/var/repo/site.git

Here we should give the repository link and not the live folder.

Let's assume that we have some great work ready in this folder. We should do the usual steps of adding the files and commit with a message:

git add .
git commit -m "My project is ready"

Just to remember, the dot after 'git add' means you are adding all files to stage. After 'git commit' we have '-m' which means we will type a message. To complete, we just 'push' everything to the server. We use the 'live' alias that we used when setting the remote.

git push live master
Counting objects: 7, done.Delta compression using up to 4 threads.Compressing objects: 100% (7/7), done.Writing objects: 100% (7/7), 10.56 KiB, done.Total 7 (delta 0), reused 0 (delta 0)To ssh://user@mydomain.com/var/repo/site.git* [new branch]      master -> master

Here we tell Git to push to the 'live' remote on the 'master' branch. To understand more about branches and how to use it you can read this tutorial.

Beta

What if you don't want to deploy everything in one step? Maybe you want to test it first and have a beta directory.

One of the ways to do that is create another repository. Let's log in again in our VPS and create our directory:

cd /var/www/
mkdir beta

To create our repository:

cd /var/repo
mkdir beta.git && cd beta.git
git init --bare

Again we should create the 'post-receive' file because we want to see our project in the beta directory:

cd hooks
cat > post-receive

Type the content of the file:

#!/bin/sh
git --work-tree=/var/www/beta --git-dir=/var/repo/beta.git checkout -f

When you finish typing, press 'control-d' to save. In order to execute the file, we need to set the proper permissions using:

chmod +x post-receive

Let's go back to our local repository:

exit
cd /my/workspace/project

So now we can set another remote pointing to our beta repository:

git remote add beta ssh://user@mydomain.com/var/repo/beta.git

With this, we can have a two step process. First we push to beta and check, and if everything is fine we push to live:

git add .
git commit -m "New version"
git push beta master

And later:

git push live master

Going Live From the Server

Maybe you have a team working in the same project and you want that others can also decide that it's time to go live. To do this, we can link the beta and live repository on the server. Log in to your VPS and type:

cd /var/repo/beta.git
git remote add live ../site.git

So now you can push from beta to live on the server:

cd /var/repo/beta.git
git push live master

Congratulations! Your VPS is now set to automatically deploy with Git!

Submitted by: Caio Vaccaro

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the author(s)

Category:
Tutorial

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
109 Comments
Leave a comment...

This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

In all examples you are accessing the repository in “~/var”, when I think should be only “/var”. Is that right?

You guys are the best! Thanks for all this info

Kamal Nasser
DigitalOcean Employee
DigitalOcean Employee badge
October 16, 2013

@maxcnunes: It should be <code>~/var</code>, I’ve updated the article.

Kamal Nasser
DigitalOcean Employee
DigitalOcean Employee badge
October 16, 2013

My bad, should be /var.

Thank you. Very useful.

Likewise, how could I cancel latest deploy?

Received the following error… I have followed every step of the tutorial…

fatal: ‘/var/repo/site.git’ does not appear to be a git repository fatal: Could not read from remote repository.

Solution found, Reference from: http://stackoverflow.com/questions/10391522/git-does-not-appear-to-be-a-git-repository

when adding the git remote. I changed ssh://user@domain/var/repo/site.git to ssh://user@domain/root/var/repo/site.git

It works now.

Same problem and solution for me too. Thanks!

yes, it work’s for me too thank you for saving me from frustating

if you are struggling to find out what the full path is, cd into the site.git file and run: $PWD

it will give you the full path of your current terminal location

for example, mine was /home/user/apps/repo/site.git instead of /root…

Great tutorial,

but I like to have my webservers as “clean” as possible. Would something like this be possible if the git repos and the website would be on different vps?

Kamal Nasser
DigitalOcean Employee
DigitalOcean Employee badge
November 30, 2013

@mikav: I don’t recommend moving the repo to a separate droplet simply because there is no need to do that. You can modify the script to rsync the website’s files to the webserver droplet however this isn’t covered in this article.

At the step “cat > post-receive” I got “-bash: post-receive: Permission denied” Same with "sudo cat > post-receive. Instead I did “sudo nano post-receive” and typed the next step in. Not surprisingly, when I did “git push live master” locally, I got:

error: insufficient permission for adding an object to repository database ./objects

fatal: failed to write object error: unpack failed: unpack-objects abnormal exit

Suggestions? Thanks.

Did you ever find a resolution for this?

I’m getting the exact same error message and can’t continue.

I too am getting this error. I’ve googled and tried to solve but cannot get my remote repo added to my Digital Ocean server.

I found this: https://stackoverflow.com/questions/27953845/bash-hooks-post-receive-permission-denied

It worked like a charm! the only thing to watch out for is in this particular example, it is assumed that you are in the parent folder to hooks so, if you’re stuck here you may have to go bad a folder to copy/paste.

I think I’m getting some kind of permission error. This is what I got:

fatal: Unable to create temporary file ‘/var/repo/site.git/./objects/pack/tmp_pack_XXXXXX’: Permission denied error: unpack failed: index-pack abnormal exit To ssh://agner@192.241.252.43/var/repo/site.git ! [remote rejected] master -> master (n/a (unpacker error)) error: failed to push some refs to ‘ssh://agner@192.241.252.43/var/repo/site.git’

Does anybody have suggestions for this problem? Thank you for the article.

Forget it.

I have found a solution.

I was pushing to an user that couldn’t write the files.

Thank you.

Can you please post your solution? I too am getting this error and cannot find a solution.

I have the same problem, can you pls post the solution? Did you change the permissions for the user?

@dinofaur any help here?

@marinus did you ever find a solution to this?

Actually fixed my own situation. My user that I created was not root (as advised in setup tutorials), and therefore did not have write access to the /var/repo location. I therefore just created the repo in my user’s home directory in a /git/ folder. That solved the permissions problem. Hopefully someone will correct me here if that was a bad idea.

I get this error after following the tut through. Great tut btw. remote: fatal: cannot exec ‘hooks/post-receive’: Text file busy

I’m having the same issue. Ever find a way to resolve this?

Kamal Nasser
DigitalOcean Employee
DigitalOcean Employee badge
January 31, 2014

@sajuna19: What’s the output of <pre>lsof | grep post-receive</pre>? Rebooting the droplet usually fixes it.

Does the hook also remove elements?

Kamal Nasser
DigitalOcean Employee
DigitalOcean Employee badge
February 1, 2014

@Fransisco: What do you mean by “remove elements”?

Hi there,

First of all, thanks for the helpful tutorials.

However, I am stuck with the tutorial documented in https://www.digitalocean.com/community/articles/how-to-set-up-automatic-deployment-with-git-with-a-vps

I have followed all the steps:

  • create directory in live server for both repo and live directory
  • run command git init --bare
  • create post-receive hook with the following code #!/bin/sh git --work-tree=~/var/www/domain.com --git-dir=~/var/repo/site.git checkout -f

(I also tried “git --work-tree=/var/www/domain.com --git-dir=/var/repo/site.git checkout -f” but no different result)

  • chmod +x post-receive
  • push project from local machine

After doing all that, I checked the /var/www/domain.com but there is no file or directory added here after git push. However, I checked the commit <sha1> in /var/repo/site.git/refs/head and there is master file and when I run command cat master it point to the correct commit key <sha1>

Just to clarify, did I do something wrong?

found a way, it turned out that I need to use absolute path in the git hook:

#!/bin/sh git --work-tree=/root/var/www/domain.com --git-dir=/root/var/repo/site.git checkout -f

I’m not sure though why the suggested steps in the tutorial didn’t work out for me.

I have to repeatedly enter my ssh password for my user every time I push live. How do add ssh keys in this type of workflow so I don’t have to enter password every time?

Just add the ssh keys to the ~/.ssh/known_hosts (for ubuntu) or ~./.ssh/authorized_keys (for some others)

How do I define my live remote with an ssh key. What is the syntax to create a git remote which is handling my private key file (for the connection)?

Hello and thanks for this nice tutorial!

I found a problem anyway, when I hit “git push” on my local machine the remote repo is updated correctly, anyway the working tree directory isn’t created and I got this message:

  • remote: fatal: This operation must be run in a work tree

Which for what I know about git is legit. So how did you make it works with bare repos? Am I missing something? Thank you!

Hello and thanks for this tuto, but i get this error: “error: cannot run hooks/post-receive: No such file or directory” i dont know what to do, help please!

I followed the instructions and had problems pushing to remote. I checked out git’s documentation and turns out a colon (:) is needed between the domain address and path when adding the remote.

For example: git remote add remotedroplet master ssh://username@address:/path/to/git/repository

Hi,

Was able to fix the issue with

  • remote: fatal: This operation must be run in a work tree by creating the folder in the /var/www - e.g. mkdir /var/www/domain.com before you can actually do the git --work-tree=~/var/www/domain.com --git-dir=~/var/repo/site.git checkout -f

Hope this helps.

I had a problem where my files were not being properly written. When I tried to git push, I was getting git’s usage statement back from the server.

It turns out that if you copy and paste the post-receive script from this webpage into nano, a line-break appears right before “checkout -f” for some reason. That’s what causes this type of error. If you run into the same thing, just make sure that entire command is on one line in the bash file.

Should checkout -f not be git checkout -f ?

Never mind me it shouldn’t be git checkout -f

@max.pittsely I had the same problem. Thanks for pointing out the fix.

So I have successfully completed every step in this fantastic tutorial to attempt to push my current Flask repo to production. However, when I push to beta/live, it seems the files are never written although I receive no errors. What are some possible debugging steps I could take?

my work tree is work-tree=/var/www/dhh/dhh which is the folder where the current files being served are located. When I cd to this folder, I only see the stuff that was previously in there.

Notes: New to using a VPS and git as well, but trying to learn!

Also, second newbie question:

If you set up a beta directory, where/how can you view the site in beta before pushing to the live branch?

Hi,

I want to make “git --work-tree=/var/www/domain.com --git-dir=/var/repo/site.git checkout -f” this line dynamic so that the same will work for any project & i will have not to edit same again and again.

I am using gitlab & projects hook directory is creating shortcut for post-receive & update hook. So this is creating problem.

Thanks in advance Alok

I have followed the tutorial and when I push to the live remote everything works fine. But, when I go to the working directory it is empty. Has anyone else run into this problem? Any help would be great. Thanks!

yes @dustin

Empty directory. Keep trying what people are posting above. Got to get there eventually!

Same situation for me as @dustin, empty working directory, but if I try to take the pull I get all pushed files in that pull, so where are my commited files if they are not in the destination directory?

And how can I dig out if the post-receive hook is really working or not?

@matthewcanty I have tried each single thing in comments above but no luck.

Got the pushing working fine, but is there a way to git pull changes I made directly on the server?

I’m wondering the same thing.

Works just fine, I was doing something wrong I guess, Thanks for this nice tutorial.

I have transferred the files from git repository to Working directory to my live server using this command(“git --work-tree=/var/www/domain.com --git-dir=/var/repo/site.git checkout -f”). but one disadvantage of doing this is that changed files are reside in both directory git repository as well as my working directory… Is there any command that can transfer or move files instead of copy ? i just want to keep my files in my working directory only…!!!

I did everything like the tutorial pointed out but was still seeing nothing being checked out to the site directory. I finally figured it out but wanted to post what caused issues for me in case it could help someone else.

Firstly, if you were’t aware, you can test the post-receive code by running it manually in shell. Just ssh into your VPS and run:

git --work-tree=/var/www/domain.com --git-dir=/var/repo/site.git checkout -f

You don’t have to continually push new code from your local repo in order to test. (unless you are trying to determine if the post-receive file is being triggered.

Now, the reason my repo wasn’t checking out any code was that when I first pushed my local commit, I pushed it to a branch called “origin”. Default checkout -f is expecting master. You can either first run checkout origin and then checkout -f or re-push from local to the master branch.

Hope that helps some of you!

I just called to say I love you.

And thank you for this tutorial

I mean it from the bottom of my heart, of my heart

Of my heart.

Also, second newbie question:

If you set up a beta directory, where/how can you view the site in beta before pushing to the live branch?

Hi,

I want to make “git --work-tree=/var/www/domain.com --git-dir=/var/repo/site.git checkout -f” this line dynamic so that the same will work for any project & i will have not to edit same again and again.

I am using gitlab & projects hook directory is creating shortcut for post-receive & update hook. So this is creating problem.

Thanks in advance Alok

I have followed the tutorial and when I push to the live remote everything works fine. But, when I go to the working directory it is empty. Has anyone else run into this problem? Any help would be great. Thanks!

yes @dustin

Empty directory. Keep trying what people are posting above. Got to get there eventually!

Same situation for me as @dustin, empty working directory, but if I try to take the pull I get all pushed files in that pull, so where are my commited files if they are not in the destination directory?

And how can I dig out if the post-receive hook is really working or not?

@matthewcanty I have tried each single thing in comments above but no luck.

Got the pushing working fine, but is there a way to git pull changes I made directly on the server?

I’m wondering the same thing.

Works just fine, I was doing something wrong I guess, Thanks for this nice tutorial.

I have transferred the files from git repository to Working directory to my live server using this command(“git --work-tree=/var/www/domain.com --git-dir=/var/repo/site.git checkout -f”). but one disadvantage of doing this is that changed files are reside in both directory git repository as well as my working directory… Is there any command that can transfer or move files instead of copy ? i just want to keep my files in my working directory only…!!!

I did everything like the tutorial pointed out but was still seeing nothing being checked out to the site directory. I finally figured it out but wanted to post what caused issues for me in case it could help someone else.

Firstly, if you were’t aware, you can test the post-receive code by running it manually in shell. Just ssh into your VPS and run:

git --work-tree=/var/www/domain.com --git-dir=/var/repo/site.git checkout -f

You don’t have to continually push new code from your local repo in order to test. (unless you are trying to determine if the post-receive file is being triggered.

Now, the reason my repo wasn’t checking out any code was that when I first pushed my local commit, I pushed it to a branch called “origin”. Default checkout -f is expecting master. You can either first run checkout origin and then checkout -f or re-push from local to the master branch.

Hope that helps some of you!

I just called to say I love you.

And thank you for this tutorial

I mean it from the bottom of my heart, of my heart

Of my heart.

DIFFICULTY: BEGINNER

I found this hard. I suck at this. Goodbye world.

I also cannot “cat > post-receive”, even with sudo. I created the file with nano instead. when I try to push, i get the same error as a couple other people:

remote: error: insufficient permission for adding an object to repository database ./objects remote: fatal: failed to write object error: unpack failed: unpack-objects abnormal exit To ssh://j[username]@[domain].com/var/repo/site.git ! [remote rejected] master -> master (unpacker error)

tried pretty much everything I could. this finally worked for me:

Not the top answer, but the answer that begins: “Usually this problem is caused by wrong user and group permissions on your Git servers file-system. The git repository has to be owned by the user and also his group.”

http://stackoverflow.com/questions/1918524/error-pushing-to-github-insufficient-permission-for-adding-an-object-to-reposi

make sure you use the $USER environment variables instead of git:gitgroup as someone mentions below that

This is an amazing tuto, simple and explanatory. Done the job in 2 min after reading it. Really cool.

Thx for this tips. But how to add a step, synchronized a repo from bitbucket.

For example :

We push on bitbucket/github and after that the online server detect update on bitbucket/github to update the repo on the server.

Best regards.

Let’s say you have a remote called live like in the tutorial:

You can add another repository link to the live remote:

Now, when you push changes, they will be sent to both repositories.

To see current settings use:

Thanks for the info

Thank you!

I got this error:

Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

I setup ssh config (on Windows) like this:

Host luyencong.com
    User anonymous
    HostName crossx.387ntg-999i.com
    IdentityFile ~/.ssh/path/to/id_rsa
Host bitbucket.org
    User git
    HostName bitbucket.org
    IdentityFile ~/.ssh/path/to/bitbucket_rsa
Host github.com
    User git
    HostName github.com
    IdentityFile ~/.ssh/path/to/github_rsa

Please help me what I need to edit to solve this issue?

In case this post-receive hooks don’t work for you :

git --work-tree=/var/www/domain.com --git-dir=/var/repo/site.git checkout -f

** try this :**

GIT_WORK_TREE=/var/www/domain.com git checkout -f

I’ve tried to start this tutorial and I’m being told that when I

cd /var
mkdir repo && cd repo
mkdir site.git && cd site.git
git init --bare

I don’t have permission so I put sudo before each of those commands. That has created all the folders and done the git init.

I was able to create the post-receive file with a sudo nano post-receive

even the chmod + x needed sudo

with all that done and after following the steps for my local machine I get the error

ssh: connect to host 188.MYIPADDRESS port 22: Bad file number
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

have I got completely the wrong permissions on the repo?

/var does not “belong” to you.

Instead make your directory for your git repo in your home folder. Well, that’s what I always do. /home/username/

Very good guide.

Can this be adapted to use two branches instead two different repos on the server? Wouldn’t it be simpler? (less repos to set up, less remotes to set up)

It looks like a waste of space… But maybe there are pitfalls that I’m not seeing…

So it would fall down to just create the bare repo somewhere (I put it directly into /var/www) and any amount of alpha, beta, master, etc folders inside /var/www, and call them the same as the branches for reusability and set the hook to:

#!/bin/bash
while read oldrev newrev refname
do
    branch=$(git rev-parse --symbolic --abbrev-ref $refname)
    # Does the branch pushed matches a directory?
    if [ -d "/var/www/$branch" ]; then
        # Yes, checkout to it…
        git --work-tree=/var/www/$branch --git-dir=/var/repo.git checkout $branch -f
    fi
done

So now the deployment would just be:

git push origin master
git push origin beta

For a multi-site structure a .git/config var could be used as:

#!/bin/bash
while read oldrev newrev refname
do
    domain=$(git var GIT_REPO_DOMAIN)
    branch=$(git rev-parse --symbolic --abbrev-ref $refname)
    # Does the branch pushed matches a directory?
    if [ -d "/var/www/$domain/$branch" ]; then
        # Yes, checkout to it…
        git --work-tree=/var/www/$domain/$branch --git-dir=/var/$domain.git checkout $branch -f
    fi
done

I don’t have a box at hand to test it… but will asap.

@declan639344 Were you able to solve the issue you were having with the remote repository? I am having the same issue and cannot figure out what to do to fix it.

I made the repos in my home directory

cd ~
mkdir repo && cd repo
mkdir site.git && cd site.git
git init --bare

from my local machine I was getting timeout errors trying to push to my droplet so I checked that I had my settings right using just ssh

ssh -l USERNAME -p PORT IPADDRESS

it turns out that I had the wrong port number but the only error I got when I tried git push was a timeout. Once this worked I was prompted to save an ssh key to the cache

once I was able to connect I set up my

git remote add ssh://USERNAME@IPADDRESS:PORT/home/USERNAME/repo/site.git

make sure you use the full path to your site.git

that’s worked for me :)

This comment has been deleted

    @declan639344 I tried this: git remote add ssh://zhunt@162.243.155.241:8930/home/zhunt/repo/gracecitysite.git

    and this: git remote add ssh://zhunt@162.243.155.241:8930/var/repo/gracecitysite.git

    and neither of those worked. It came back with a usage statement for git remote add

    @tech1002985 Sorry, you need to have a name for the destination git

    git remote add live ssh://zhunt@162.243.155.241:8930/home/zhunt/repo/gracecitysite.git
    

    How do you pull changes made on the live server into your local directory?

    When I added the remote directory I added it in my local git directory with ‘ssh://user@mydomain.com/var/repo/site.git’. To clarify, what is the user@mydomain supposed to be? Is ‘user’ the user I am logged into my server with? Is ‘mydomain’ the domain I want to publish to? Can someone clarify that for me?

    @tech1002985 I created a user called declan which I use to connect to my droplet over ssh in this doc they use a user named ‘demo’ https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-14-04

    rather than use mydomain I just use the IP address for my droplet

    I made a post with what worked for me, you should see it listed here: https://www.digitalocean.com/community/users/declan639344

    Does this method still work? I’ve followed all the steps and running ‘git push live master’ seems to do something but when I look on my server I can’t see any files despite it saying it’s pushing the files… :S

    I’ve noticed that this method reverts my file permissions (and group ownership) that I’ve setup to that of my local files. Is there a way that I can prevent this from happening? I assume I could add it to post checkout but wanted to see if there was another option. Thanks!

    Thanks so much. This is great!

    I was getting the “fatal: ‘/var/repo/site.git’ does not appear to be a git repository” error.

    I updated the remote to this, Note the ‘colon’…

    git remote add live user@example.org:/var/repo/site.git

    note that if /var/repo and /var/www/domain.com are owned by root but you’re ssh-ing in as user foo, and sudo requires a password that the git hooks will fail due to lack of permissions. the easy (someone else can decide if this is problematic or not) fix is to simply change the ownership of /var/www and /var/repo to your user and group: sudo chown -R foo:foo /var/www and sudo chown -R foo:foo /var/repo

    But it will deny other users from deploying the change in remote server

    So, is there a solution to allow multiple different users to deploy?

    Great article! More of this please!

    Author forgot about chmod for post-receive for beta.

    I tried to push-deploy changes to remote server. It works fine. But it seems like it modifies the file ownership that is the remote server. For this reason other users can’t deploy the changes.

    Is there any way to deploy the changes without modifying the ownership/permission?

    Thanks for the tutorial, everything worked flawlessly. I’m trying to figure out a workflow that would include submodules of a repo. This method will only add the empty directory for a submodule. then if i were to CD into the the “repo.git” directory on server, and do a git submodule update --init, i get back fatal: /usr/lib/git-core/git-submodule cannot be used without a working tree.

    If you want the default branch to be something other than master, i.e develop On the site.git directory do:

    git symbolic-ref HEAD refs/heads/develop
    

    Which will update the HEAD file in your repository so that it contains:

    ref: refs/heads/develop
    

    Taken from here

    when pushing, the repo is receiving, but nothing is “deployed” to my “/var/www/domain.com”. I put echo “hello” into the hook to see if it responded - and it does. But nothing is changing on the “domain.com end”. Not sure how to troubleshoot this. Any ideas?

    Need some help here… after I do the

    git push live master
    

    and saw * [new branch] master -> master

    I went back to my server via ssh, and nothing happened, none of the files were added. Why?

    Hey guys, just created this on my server, super great tutorial, is their in some way that you could add more bash commands is that done in post-receive ?

    There are also free or inexpensive service providers out there that automate most of this for you. For example, REPOMAN.IO will get you up and running and also includes a hand-full of other features that might be useful (logging, invite team members, etc).

    Great tutorial. Thanks!

    I always get this while pushing to live master

    bash: git-receive-pack: command not found fatal: Could not read from remote repository.

    When i run this command on the remote machine git-receive-pack it works fine!

    One of the things you left out is permissions between users. With these instructions as-is, this would only work if the repo, web folder and deploy-user were all root, which is not advised.

    On an nginx server for example, the web directory and repos would be owned by www-data and each deploying user would be in the www-data group.

    Additionally, conventionally speaking, live should be production and beta should be staging, and while in the end it really doesn’t matter what these remotes are called, these terms are more globally recognized by readers.

    Anybody experiencing permissions issues should look at your permissions. Try something like this…

    ssh me@myserver
    cd repository.git
    
    sudo chmod -R g+ws *
    sudo chgrp -R mygroup *
    
    git config core.sharedRepository true
    

    This is so awesome! One thing that caught me out was I needed to switch

    git remote add live user@....

    with

    git remote add live root@...

    because there was no user called user obviously

    When I push the first time I get error:

    fatal: ‘/root/var/repo/site.git’ does not appear to be a git repository fatal: Could not read from remote repository.

    Please make sure you have the correct access rights and the repository exists.

    Hi, This only works to ‘copy’ source files from master branch to /var/www/domain.com?

    What should I do if I want to ‘copy’ source files from another branch to /var/www/domain.com?

    Thanks!

    Instead of

    git push origin master
    

    You can do:

    git push origin newbranch
    

    For those who might stumble on the part where they try to do their first push and get something like this:

    error: src refspec master does not match any.
    error: failed to push some refs to 'ssh://user@mydomain.com/var/repo/site.git'
    

    Go back a couple of steps and remove your local repository.

    rm -rf .git
    

    Then reinitialize it with this command:

    git remote add live -f --mirror=fetch ssh://user@mydomain.com/var/repo/site.git
    

    This will run a fetch immediately as the remote is setup with -f and then --mirror=fetch will also download all remote references from the bare repository.

    There aren’t any references yet, since its still a bare repo on the server, so maybe you can test it out with just -f as well.

    But this got me going.

    Not a IT professional, I am having difficulties in working through the tutorial. Can somebody please help me:

    1. If my DO server/droplet has not been associated with a domain name, should I use user@IP in “user@mydomain.com”? Is “user” in “user@mydomain.com” the username for DO server/droplet?

    2. I have private repository created in github. Typically, only github account added by me as contributor can access the repository. I did not see any info being entered or asked in above tutorial. How can it connects the github repository with the /var/repo/site.git? My understanding is that github, once installed at the droplet/server and login credential entered, will connect to the the github.com for sync. However,

    3. I see that when git is installed, the git configuration has: user.name=Your Name user.email=youremail@domain.com but, still no password entered to login to the git account.

    Thanks…

    Have you gone through any setup tutorials, have you setup a regular user with sudo permissions? If not, start here.

    1. Yes, use user@IP. “user” is the username you setup, if you haven’t set one up yet you will have to use root. If you’re at this stage please read the above link.

    2. You’re getting git and github.com confused. Git can be used without gihub.com as is being done in this tutorial. We’re pushing from our local git to our DO git. If you see git push origin master in the tutorial that is usually a push to github but is not needed to utilize this tutorial. In your existing workflow you’re probably pushing to gihub, now you will push to DO and once everything looks ok there then I would suggest you push to github.

    3. I would suggest using ssh keys instead of passwords but you can read here on saving your password.

    When I do sudo cat > post-receive I get “-bash: post-receive: Permission denied”

    Try this:

    sudo bash -c 'cat > post-receive'
    

    Explanation here

    I’m getting this error when I have tried to push to live

    remote: fatal: Unable to create temporary file '/var/repo/./objects/pack/tmp_pack_XXXXXX': Permission denied
    error: pack-objects died of signal 13
    

    I created a user non-route user and gave super user permission when i set up the server. Any advice?

    Thanks for the wonderful tutorial.

    I’ve been trying to get it working right. I am stuck with two issues.

    I’ve a project with several branches in my local machine. The DO droplet has two repos in /var/repo namely live-repo.git and staging-repo.git and two folders in /var/www for the apache server, namely live and staging

    The post receive hook of the staging repo

    git --work-tree=/var/www/staging --git-dir=/var/repo/staging-repo.git checkout -f
    

    The post receive hook of the live repo

    git --work-tree=/var/www/live --git-dir=/var/repo/live-repo.git checkout -f
    

    PROBLEM #1 When I push my local master to live, instead of updating only the live folder in /var/www, it updates both the live and staging folders with the content. This happens for all my branches when pushed to either live or staging

    ie. Both live and staging folders in /var/www are updated when i push code from my local machine with any of the following commands

    • git push live [any-branch]
    • git push staging [any-branch]

    PROBLEM #2 Secondly, I lose my latest content on sshing into the server and restarting apache from there. The latest pushed contents vanishes and and older version of the site loads when apache is restarted

    Any help is greatly appreciated

    Thank for sharing.but after i push live all code on server it show 404 not found. what is the problem ? can someone help ? thank you.

    and what if you want to make an urgent rollback to an old version without the last changes?

    or just test an specific branch in beta or production enviroment?

    Thanks!!

    hi,

    I’m trying deploy all the locale stuff, on the server, so:

    /var/www/where_to_deploy (apache2 is reading from here). /var/repo/repo.git (origin repo) and /some/path/locale_repo (locale 1 master branch)

    I have no problem to push to repo.git. But i need to --detach or checkout to a dummy branch before the push will be accepeted from the server. This is it the minor of the problem

    The problem is that /var/www/where_to_deply isn’t updated, any pushed file is updated inside this directory. What i’m doing wrong?

    If I am using bitbucket or git how would I include them in the setup? Would my post-receive directory path setting be my url to my bitbucket or git account?

    Thank you for this. Is it possible to pull from this server repo also? I have a django project that I’ve configured on the live server and want to pull it down into my local machine?

    Great tutorial!

    One problem I had: the “/var/www/domain.com” folder in your code on the post-receive file must exist when you push to the live remote, otherwise you’ll get “remote: fatal: This operation must be run in a work tree” . In other words, it won’t create the folder for you. That might be an obvious thing for some but wasn’t for me.

    Awesome tutorial!!

    To solve the “insufficient permission” error http://stackoverflow.com/a/6448326

    I tried but explodes:


    $ git push live master ssh: connect to host domain.com port 22: Network is unreachable fatal: Could not read from remote repository.

    Please make sure you have the correct access rights and the repository exists.

    • I am using cloudflare, what’s the problem?
    • domain.com is not the real domain

    Thanks

    I am author of two possible alternatives to the same problem.

    First one is the open-source incoming webhook server that can execute commands, you can find it at https://github.com/adnanh/webhook and the bitbucket hook example at https://github.com/adnanh/webhook/wiki/Hook-Examples

    Second one is Hookdoo and it follows a little bit different approach. However, it is a paid Software-as-a-Service solution, but it requires you to do zero setup on the server. When you register for the first time, you will receive a month of free trial so you can try it out, and we can help you set it up. You can check it out at https://www.hookdoo.com/

    Hi - I’m trying to start my server using pm2 but I’m unsure of how to access my startup file ? In my local file structure it’s located in ~/server/main.js but how can I access this through the git structure that’s on my server now?

    I was having the issue of my bare repo for some reason not being recognised as a git repository by the checkout command.

    I found following the guide here worked instead.

    Great tutorial! It is working for me to push to live if the ssh connection is without ssh key. But what if I have an ssh key for connection? I don’t find the syntax how to create a live remote with ssh connection with keys? Does anybody have a solution?

    Hello!

    When we set up the git bare repository the branch that is setup by default is master as it is in the HEAD file when running “cat HEAD”:

    ref: refs/heads/master
    

    As it is a git bare repo we don’t have access to commands to change the branch that is in HEAD. Have we to change manually in HEAD file the branch from master to dev, or that is other way to switch between branches?

    Thanks for the important tutorial.

    fatal: ‘/root/var/repo/site.git’ does not appear to be a git repository fatal: Could not read from remote repository.

    Please make sure you have the correct access rights and the repository exists.

    –Same issue above shows with or without /root/ in remote ssh url

    Good write up. All but forgetting to use sudo commands, which will land you in hot water very quickly, as all comments pointing permission issues. Also, you need to execute your post-receive hooks as a www-data user.

    #!/bin/sh
    sudo -u www-data git --work-tree=/root/var/www/domain.com --git-dir=/root/var/repo/site.git checkout -f
    

    Notwithstanding make sure you have correct file/folder permissions for the user running ssh to the server.

    Thanks for the tuto! He made my life more easy 😋

    For the Beta folder is in /var/www or /var/www/html Cause how to access your beta website for testing purpose? Thanks

    You have to set correct permission for the .git folder on server. I had the following error on pushing to repo when the folder had root:root ownership:

    error: pack-objects died of signal 13
    

    Solution:

    cd /var/repo
    sudo chown -R user:user site.git
    

    where ‘user’ is your user or a dedicated git user, etc

    Hi, I’ve been following the step by step. everything went well. However, when I push live, it tells me everything is up to date, but I think my code is not deploying, as my site not updating. Any help, please?

    Does anyone knows how to pull this off under the load-balanced servers? My server architecture is as follows

                    Load Balancer
        -------------------------------------
        |                   |               |
    Server 1            Server 2        Server3
        |                   |               |
        -------------------------------------
                            |
                        Database Server
    
    

    The server might scale up or down depending on the requirements. Any help is really appreciated.

    I’m getting the following error

    root@host.com: Permission denied (publickey). fatal: Could not read from remote repository.

    Please make sure you have the correct access rights and the repository exists.

    I’m getting the following errors

    root@MYSITE.com: Permission denied (publickey). fatal: Could not read from remote repository.

    Please make sure you have the correct access rights and the repository exists.

    Try DigitalOcean for free

    Click below to sign up and get $200 of credit to try our products over 60 days!

    Sign up

    Join the Tech Talk
    Success! Thank you! Please check your email for further details.

    Please complete your information!

    Become a contributor for community

    Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

    DigitalOcean Documentation

    Full documentation for every DigitalOcean product.

    Resources for startups and SMBs

    The Wave has everything you need to know about building a business, from raising funding to marketing your product.

    Get our newsletter

    Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

    New accounts only. By submitting your email you agree to our Privacy Policy

    The developer cloud

    Scale up as you grow — whether you're running one virtual machine or ten thousand.

    Get started for free

    Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

    *This promotional offer applies to new accounts only.