Git Post-Receive钩子用于网站分段

我试图设置Git来升级我的网站,这样我就可以通过git pull来获取当前版本在本地工作,然后通过git push将更改git push送到远程服务器。 我已经设置好了,以便按照我想要的方式工作,但是在推送之后,我必须在远程服务器上手动运行git checkout -fgit reset --hard HEAD

我已经尝试把这些放在shell脚本中作为服务器上的post-receive钩子,但是它似乎没有任何作用。 我知道脚本正在运行,因为我看到“推送到服务器的变化”,我推。 这是后接收钩:

 #!/bin/sh git reset --hard HEAD echo "Changes pushed to server." 

你的问题的答案在这里: http : //toroid.org/ams/git-website-howto

总之,你想要做的是添加一个“分离的工作树”裸仓库。 通常你认为你的工作树包含.git目录。 裸仓库根据定义没有工作树,但是只要它位于不同于裸仓库的目录中,就可以创build一个仓库。

post-receive钩子只是一个简单的git checkout -f来将仓库的HEAD复制到工作目录中。 Apache使用它作为它的文档根目录,并且你全都设置好了。 无论何时您推送到裸仓库,Apache都会立即开始提供服务。

我通常使用它来自动推送到一个登台服务器,看看“真实”的环境会呕吐我的变化。 部署到实时服务器是一个完全不同的故事。 🙂

2015年3月更新

正如我在“ 将更改推送到远程存储库时是什么Git警告消息? ”中所提到的那样,您实际上可以直接将其推送到非裸回购(Git 2.3.0+,2015年2月):

 git config receive.denyCurrentBranch updateInstead 

相应地更新工作树,但如果有任何未提交的更改,则拒绝这样做。

这将允许你避免任何post-receive钩子。


(原文解答:2010年10月)

GitFAQbuild议非裸回购这个更新后的钩子:
(它可能会给你更多的线索,看看钩子执行过程中究竟发生了什么,注意这是一个更新后的钩子,而不是后接收)

 #!/bin/sh # # This hook does two things: # # 1. update the "info" files that allow the list of references to be # queries over dumb transports such as http # # 2. if this repository looks like it is a non-bare repository, and # the checked-out branch is pushed to, then update the working copy. # This makes "push" function somewhat similarly to darcs and bzr. # # To enable this hook, make this file executable by "chmod +x post-update". git-update-server-info is_bare=$(git-config --get --bool core.bare) if [ -z "$is_bare" ] then # for compatibility's sake, guess git_dir_full=$(cd $GIT_DIR; pwd) case $git_dir_full in */.git) is_bare=false;; *) is_bare=true;; esac fi update_wc() { ref=$1 echo "Push to checked out branch $ref" >&2 if [ ! -f $GIT_DIR/logs/HEAD ] then echo "E:push to non-bare repository requires a HEAD reflog" >&2 exit 1 fi if (cd $GIT_WORK_TREE; git-diff-files -q --exit-code >/dev/null) then wc_dirty=0 else echo "W:unstaged changes found in working copy" >&2 wc_dirty=1 desc="working copy" fi if git diff-index --cached HEAD@{1} >/dev/null then index_dirty=0 else echo "W:uncommitted, staged changes found" >&2 index_dirty=1 if [ -n "$desc" ] then desc="$desc and index" else desc="index" fi fi if [ "$wc_dirty" -ne 0 -o "$index_dirty" -ne 0 ] then new=$(git rev-parse HEAD) echo "W:stashing dirty $desc - see git-stash(1)" >&2 ( trap 'echo trapped $$; git symbolic-ref HEAD "'"$ref"'"' 2 3 13 15 ERR EXIT git-update-ref --no-deref HEAD HEAD@{1} cd $GIT_WORK_TREE git stash save "dirty $desc before update to $new"; git-symbolic-ref HEAD "$ref" ) fi # eye candy - show the WC updates :) echo "Updating working copy" >&2 (cd $GIT_WORK_TREE git-diff-index -R --name-status HEAD >&2 git-reset --hard HEAD) } if [ "$is_bare" = "false" ] then active_branch=`git-symbolic-ref HEAD` export GIT_DIR=$(cd $GIT_DIR; pwd) GIT_WORK_TREE=${GIT_WORK_TREE-..} for ref do if [ "$ref" = "$active_branch" ] then update_wc $ref fi done fi 

为此,您仍然需要特别允许通过使用以下任一configuration设置将更改推送到当前分支:

 git config receive.denyCurrentBranch ignore 

要么

 git config receive.denyCurrentBranch warn 

我有完全相同的问题。 在回复这个链接: http : //toroid.org/ams/git-website-howto – 下面的命令已经做到了:

 sudo chmod +x hooks/post-receive 

我们错过了一个sudo权限,首先configuration了这些东西。

VonC脚本的固定版本适用于我(绝对没有保证)。

 #!/bin/sh # # This hook does two things: # # 1. update the "info" files that allow the list of references to be # queries over dumb transports such as http # # 2. if this repository looks like it is a non-bare repository, and # the checked-out branch is pushed to, then update the working copy. # This makes "push" function somewhat similarly to darcs and bzr. # # To enable this hook, make this file executable by "chmod +x post-update". set -e git update-server-info is_bare=$(git config --get --bool core.bare) if [ -z "${is_bare}" ] then # for compatibility's sake, guess git_dir_full=$(cd $GIT_DIR; pwd) case $git_dir_full in */.git) is_bare=false;; *) is_bare=true;; esac fi update_wc() { ref=$1 echo "Push to checked out branch $ref" >&2 if [ ! -f ${GIT_DIR}/logs/HEAD ] then echo "E:push to non-bare repository requires a HEAD reflog" >&2 exit 1 fi if (cd ${GIT_WORK_TREE}; git diff-files -q --exit-code >/dev/null) then wc_dirty=0 else echo "W:unstaged changes found in working copy" >&2 wc_dirty=1 desc="working copy" fi if git diff-index --cached HEAD@{1} >/dev/null then index_dirty=0 else echo "W:uncommitted, staged changes found" >&2 index_dirty=1 if [ -n "$desc" ] then desc="$desc and index" else desc="index" fi fi if [ "$wc_dirty" -ne 0 -o "$index_dirty" -ne 0 ] then new=$(git rev-parse HEAD) echo "W:stashing dirty $desc - see git-stash(1)" >&2 ( trap 'echo trapped $$; git symbolic-ref HEAD "'"$ref"'"' 2 3 13 15 ERR EXIT git update-ref --no-deref HEAD HEAD@{1} cd ${GIT_WORK_TREE} git stash save "dirty $desc before update to $new"; git symbolic-ref HEAD "$ref" ) fi # eye candy - show the WC updates :) echo "Updating working copy" >&2 (cd ${GIT_WORK_TREE} git diff-index -R --name-status HEAD >&2 git reset --hard HEAD # need to touch some files or restart the application? do that here: # touch *.wsgi ) } if [ x"${is_bare}" = x"false" ] then active_branch=$(git symbolic-ref HEAD) export GIT_DIR=$(cd ${GIT_DIR}; pwd) GIT_WORK_TREE="${GIT_DIR}/.." for ref in $(cat) do if [ x"$ref" = x"${active_branch}" ] then update_wc $ref fi done fi 

简单的脚本来设置这个git部署:

准备接收后挂钩:

 echo '#!/bin/sh' > .git/hooks/post-receive echo 'git checkout -f' >> .git/hooks/post-receive echo 'git reset --hard' >> .git/hooks/post-receive chmod +x .git/hooks/post-receive 

允许推入这个存储库,尽pipe它不是光秃秃的:

 git config receive.denycurrentbranch false 

我只是猜测,但这可能是一些权限问题(完整path需要? cd ?)。 检查日志文件中确实发生了什么。

但是,通过git发布文件始终只是发布过程的一个任务。 您通常需要复制一些文件,删除其他,设置,更新权限,生成文档等。

对于复杂的解决scheme,构build脚本可能比任何git钩子都好。 可以很好地处理这些任务的工具:

  • phing (或ant)
  • 哈德森 + git插件

(我意识到这不是你所期待的答案,但是作为评论发表太久了)

Interesting Posts