问题
The basic setup of our Git workflow is a bare repository on a local network server with two developers pushing/pulling to it.
We would like to automagically copy (checkout) each branch that gets pushed to a different location on our local network server. To exemplify:
Pushing the 'develop' branch copies to 'develop' sub-folder. Pushing the 'master' branch copies to the 'master' sub-folder.
The problem we are having is getting the post-receive hook to do this. Here is what we currently have:
#!/bin/bash
while read oldrev newrev ref
do
branch=`echo $ref | cut -d/ -f3`
if [ "master" == "$branch" ]; then
GIT_WORK_TREE=/master
git checkout -f $branch
echo 'Changes pushed master.'
fi
if [ "develop" == "$branch" ]; then
GIT_WORK_TREE=/develop
git checkout -f $branch
echo 'Changes pushed to develop.'
fi
done
The error received is:
'remote: fatal: This operation must be run in a work tree remote: Changes pushed to develop.'
As you would expect from that error - nothing is actually checked out.
I had also tried the post-receive this way but the same issue:
#!/bin/bash
while read oldrev newrev ref
do
branch=`echo $ref | cut -d/ -f3`
if [ "master" == "$branch" ]; then
git --work-tree=/master checkout -f $branch
echo 'Changes pushed master.'
fi
if [ "develop" == "$branch" ]; then
git --work-tree=/develop checkout -f $branch
echo 'Changes pushed to develop.'
fi
done
Can anyone explain what I am doing wrong here (feel free to explain it like you would to a 3-year old :)). Thanks.
To make the answer clearer for future readers, Torek hit it on the head. I was using --work-tree=/master
to try and get to to a folder called 'master' inside the root of my bare repo (e.g. alongside 'branches', 'hooks' etc). As soon as I changed this to --work-tree=./master
(note the dot before the forward slash) everything worked as I expected.
回答1:
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).
回答2:
you should put 'GIT_WORK_TREE=/master git checkout -f $branch' in one line, then it worked, after read your post, my post-receive is :
#!/bin/sh
while read oldrev newrev ref
do
branch=`echo $ref | cut -d/ -f3`
if [ "master" == "$branch" ]; then
GIT_WORK_TREE=/home/tnj/www/www.test.com git checkout -f $branch
chmod -R 775 /home/tnj/www/www.test.com/
echo 'changes pushed to www.test.com'
fi
if [ "develop" == "$branch" ]; then
GIT_WORK_TREE=/home/tnj/www/www.test.com.dev git checkout -f $branch
chmod -R 775 /home/tnj/www/www.test.com.dev/
echo 'changes pushed to www.test.com.dev'
fi
done
it worked fine, thank you for your post ! :)
来源:https://stackoverflow.com/questions/19269426/git-post-receive-hook-to-checkout-each-branch-to-different-folders