Git Post-Receive Checkout to Remote Machine

Hook post-receive does not work after push from local to remote repository

Ok, I've found what the problem was - the partition on the host is mounted as noexec. If so, the hooks cannot work.

This is for security reasons. It's typical situation on shared hosting.


My alternative solution:

We can create a git alias where you can run a bash script with ssh logging and run the git command directly on the server

How to do it?

In the local repository configuration file we add an alias:

[alias]
run = "!sh ./hook.sh"

(as you can see in the example, this alias will launch the hook.sh file)

Now we create a hook.sh file with git commands

#!/bin/bash

ssh user@host -p [port] 'bash -s' <<-EOF
git --work-tree=/home/xxxxxx/xxxxxx/public_html/prod --git-dir=/home/xxxxxx/xxxxxx/dev.git checkout -f
exit
EOF

And now we just have to use the git run command

Note: This is just a simple example. You have to test it on your envoirment!

git post-receive checkout to remote machine?

GIT_WORK_TREE=/bar means that bar is a git repo.

If bar is a git repo on the remote side, then it can pull from a bare repo bare_bar.git (also on the remote side), to which you can push to.

In other words, your post-receive hook would push to bare_bar repo through ssh, and a post-receive hook on that bare repo would trigger the pull from the actual repo bar: see "Creating a git repository from a production folder".


I'd prefer a solution that keeps the remote server free of any .git dirs (and even the git package itself ideally)

In that case, your current post-receive hook and its rsync command seems to be the only way to incrementally copy new data to a remote working tree.

  • git archive would archive everything each time.
  • git bundle would require git on the other side.

Git post-receive hook to checkout each branch to different folders?

You're getting this because /master and /develop are non-existent directories:

$ git --work-tree=/nonexistent checkout master
fatal: This operation must be run in a work tree

You may also want to see my answer to a question about another problem that crops up with this approach, which also addresses a small bug you've copied from a popular-but-wrong post-receive technique (the use of cut to parse the updated ref).

[Your phrasing also makes me wonder if you are thinking of deploying those two branches into a sub-directory within the (presumably --bare) repository that is receiving the pushes. This is probably not a great idea.]

Another (different) method for deploying is to have a "real" git tree in the deployment location. Then, instead of git --work-tree=... checkout you do something like this instead:

deploy()
{
local path=$1 branch=$2

(cd $path && unset GIT_DIR && git fetch && git checkout -f origin/$branch)
}

(untested, feel free to experiment and/or modify). This has other, slightly different tradeoffs with respect to disk space and update windows (which I mention in the other answer).

Git post-receive hook for push-to-deploy .. I want to checkout last pushed branch

Yes, you can, like this:

#!/bin/bash
while read oldrev newrev refname
do
branch=$(git rev-parse --symbolic --abbrev-ref $refname)
git --work-tree=/var/www/myproject checkout -f $branch
done

taken from: here

Git Post-Receive Hook for Website Staging

The answer to your question is here: http://toroid.org/ams/git-website-howto

In short, what you want to do is add a "detached work tree" to the bare repository. Normally you think of your work tree as containing the .git directory. Bare repositories do not have a work tree by definition, but you can create one as long as it's in a different directory than the bare repo.

The post-receive hook is just a simple git checkout -f to replicate the repository's HEAD into the work directory. Apache uses that as its document root, and you're all set. Any time you push to the bare repository, Apache will immediately start serving it.

I generally use this to automatically push to a staging server to see if the "real" environment will puke on my changes. Deploying to the live server is a completely different story. :-)

Run git post-receive hook as user1, and checkout as user2

Another option would be for the git-user to create an archive that contains all the relevant files to be deployed (think of it as an artefact). This can be done in the post-receive hook before touching the trigger file. To create the ZIP/TAR, you can use the git archive command which facilitates this step.

As soon as the cron-job runs and a deploy is triggered, the site-user extracts the contents of the archive into /var/www/site and removes the archive.

This way, the git-user has no access to the webroot. At the same time, the site-user does not even need read-access to the repository.


It is also possible to specify an alternative index-file with the environment variable GIT_INDEX_FILE to circumvent the default location ($GIT_DIR/index). But I don't know if Git needs write access to other files/folders as well.

Git checkout in post-receive hook: Not a git repository '.'

[Edit, Feb 2017: this old answer still gets hit a bit, so let's add a few notes. (1) This kind of live update is often a bad idea: be sure you know why you're doing it, and that you won't clobber your own work. (2) In Git since 2.3, you can now configure receive.denyCurrentBranch to updateInstead, plus a hook tweak in Git 2.4 and later. For details, see the git config documentation.]

The post-receive hook is run with $GIT_DIR set to .. This causes git to look for ./HEAD, ./refs/heads/master, etc., rather than .git/HEAD, .git/refs/heads/master, etc. But, since you don't do anything to change $PWD in the hook (as shown anyway), the hook will be running in the .git subdirectory (/home/andrew/web/.git), and hence this failure is quite mysterious: . will in fact be a valid git repository.

One standard trick that avoids hard-coding the path name is to use cd ..; git checkout -f as the post-receive hook. This is where the setting of $GIT_DIR becomes a problem, because after cd .. the hook is running in (still assuming this case) /home/andrew/web and of course at that point, $GIT_DIR should be .git rather than .. The standard fix for that is simply to unset GIT_DIR (setting it to .git would also work).

Your post-receive hook as shown works fine for me, though (with appropriate hard-coded-path changes). Then again I am pushing from a Unix-like machine, not a PC. Is it possible there's something else happening, that changes directories out of the .git subdirectory? You can do something like echo running in $PWD in the hook to see where you are.



Related Topics



Leave a reply



Submit