用于网站暂存的 Git 接收后挂钩

发布于 2024-09-26 01:05:47 字数 391 浏览 6 评论 0原文

我正在尝试设置 Git 来暂存我的网站,以便我可以 git pull 使当前版本在本地运行,然后 git push 将更改推送到远程服务器。我已经将其设置为按照我想要的方式工作,但是在推送后,我必须手动运行 git checkout -f 或 git reset --hard HEAD< /code> 在远程服务器上。

我尝试将它们放入 shell 脚本中作为服务器上的 post-receive 挂钩,但它似乎没有任何效果。我知道脚本正在运行,因为我在推送后看到“更改已推送到服务器”。这是接收后挂钩:

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

I'm trying to set up Git for staging my website so that I can git pull to get the current version to work on locally and then git push to push the changes to the remote server. I've got it set up so that it works the way I want it to, but after I push, I have to manually run git checkout -f or git reset --hard HEAD on the remote server.

I've tried putting these into a shell script as the post-receive hook on the server, but it just doesn't seem to have any effect. I know that the script is running because I'm seeing "Changes pushed to server" after I push. Here's the post-receive hook:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

夜巴黎 2024-10-03 01:05:47

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

简而言之,您要做的就是向裸存储库添加一个“分离的工作树”。通常,您认为工作树包含 .git 目录。根据定义,裸存储库没有工作树,但只要它位于与裸存储库不同的目录中,您就可以创建一个工作树。

post-receive 挂钩只是一个简单的 git checkout -f ,用于将存储库的 HEAD 复制到工作目录中。 Apache 使用它作为其文档根目录,您就完成了。每当您推送到裸存储库时,Apache 都会立即开始为其提供服务。

我通常使用它来自动推送到临时服务器,以查看“真实”环境是否会影响我的更改。部署到实时服务器是一个完全不同的故事。 :-)

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. :-)

走野 2024-10-03 01:05:47

2015 年 3 月更新

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

git config receive.denyCurrentBranch updateInstead

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

这将使您避免任何接收后挂钩。


(原始答案:2010 年 10 月)

GitFAQ 建议 < a href="http://sitaramc.github.com/concepts/bare.html#all_about_bare_repos_what_why_and_how_to_fix_a_non_bare_push" rel="nofollow noreferrer">非裸仓库此更新后挂钩:
(它可能会为您提供有关挂钩执行中实际发生的情况的更多线索。请注意,这是更新后挂钩,而不是接收后)

#!/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

为此,您仍然需要专门允许将更改推送到使用以下配置设置之一来当前分支:

git config receive.denyCurrentBranch ignore

git config receive.denyCurrentBranch warn

Update March 2015

As I mentioned in "What is this Git warning message when pushing changes to a remote repository?", you actually can push directly to a non-bare repo now (Git 2.3.0+, February 2015) with:

git config receive.denyCurrentBranch updateInstead

Update the working tree accordingly, but refuse to do so if there are any uncommitted changes.

That would allow you to avoid any post-receive hook.


(Original answer: Oct 2010)

The GitFAQ recommends for non-bare repo this post-update hook:
(it might give you more clue as to what is actually going on in the hook execution. Note this is a post-update hook, not a post-receive)

#!/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

For this to work, you would still need to specifically allow pushing changes to the current branch by using either one of these configuration settings:

git config receive.denyCurrentBranch ignore

or

git config receive.denyCurrentBranch warn
迷荒 2024-10-03 01:05:47

我有完全相同的问题。在对此链接的回复中: http://toroid.org/ams/git-website-howto -以下命令已完成此操作:

sudo chmod +x hooks/post-receive

我们错过了首先配置这些内容的 sudo 权限。

I had the exact same issue. In a reply to this link: http://toroid.org/ams/git-website-howto - The following command has done it:

sudo chmod +x hooks/post-receive

We missed a sudo permission first configured the stuff.

岁月流歌 2024-10-03 01:05:47

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

Fixed version of VonC's script, works for me (absolutely no guarantees).

#!/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
两仪 2024-10-03 01:05:47

用于设置此 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

允许推送到此存储库,尽管它不是裸露的:

git config receive.denycurrentbranch false

Simple script for setting this git deployment:

Preparing post-receive hook:

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

Allowing push into this repository, though it is not bare:

git config receive.denycurrentbranch false
浪荡不羁 2024-10-03 01:05:47

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

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

对于复杂的解决方案,构建脚本可能比任何 git hook 更好。可以很好地处理这些任务的工具:

(我意识到这不是您期望的答案,但作为评论发布太长了)

I'm just guessing, but this may be some permission issue (full path needed? cd?). Check what is really happening in the log files.

However publishing the files via git is always just one tasks of the publishing process. You usually need to copy some files, delete other, setup, update permissions, generate docs etc.

For a complex solution a build script might be better than any git hook. Tools which can handle those tasks very well:

(I realize this is not the answer you are expecting, but it's too long to post as a comment)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文