git post接收挂钩不';我似乎无法处理其他分支

git post接收挂钩不';我似乎无法处理其他分支,git,Git,我希望你们在生活中做得很好。我不是git的专家,但自从我开始使用它以来,我非常喜欢它 我在我的客户服务器上有两个存储库,即live.git和beta.git,通过在互联网上学习一些教程,我能够设置hook,post-receive-one,为文件创建一个工作目录(分别是/和/beta/目录)。该项目是一个web应用程序,因此每当我进行更改时,我只需将它们推送到存储库,post receive钩子就会更新工作目录中的文件 问题是我最近创建了一个新分支(称为Angular),现在如果我这样做了 gi

我希望你们在生活中做得很好。我不是git的专家,但自从我开始使用它以来,我非常喜欢它

我在我的客户服务器上有两个存储库,即
live.git
beta.git
,通过在互联网上学习一些教程,我能够设置hook,post-receive-one,为文件创建一个工作目录(分别是
/
/beta/
目录)。该项目是一个web应用程序,因此每当我进行更改时,我只需将它们推送到存储库,post receive钩子就会更新工作目录中的文件

问题是我最近创建了一个新分支(称为
Angular
),现在如果我这样做了

git push beta Angular 
它确实会将更新推送到存储库,但现在工作目录不受影响。工作目录仍然显示来自
分支的更改

以下是我的帖子的内容:

#!/bin/sh
echo "Performing post-receive actions on beta.."
git --work-tree=/home/webapp/public_html/beta --git-dir=/home/webapp/public_html/beta.git checkout -f
我在这里没有看到任何关于
master
或任何分支的提及,这就是为什么我甚至不能在这里尝试不同的东西

有没有人能帮助我理解,我怎样才能做到无论推哪个分支,它都会根据最后一个推的分支更新工作目录中的文件

提前感谢大家,感谢你们抽出时间

编辑: 我的问题是:

1) 为什么它处理
master
分支我的默认值

2) 是否有任何配置指定默认情况下使用
git--work tree
命令只处理
master
分支

3) 是否仍然需要硬编码将哪个分支写入
工作树
?因为我可能只会将分支推到
beta.git
,而将另一个分支推到
live.git

有没有人能帮助我理解,我怎样才能做到无论推哪个分支,它都会根据最后一个推的分支更新工作目录中的文件

如果我跑步怎么办,例如:

git push origin branch1 branch2 branch3
??考虑到我刚刚用一次推送更新了三个分支,您希望部署哪个分支

无论如何,答案有点复杂。其中一部分非常简单:任何post接收钩子都可以(而且大多数人都应该)读取标准输入中的每一行。如中所述,每一行都充当一个指令。输入格式与的相同,因此请阅读该部分

您可以通过找到许多post-receive部署挂钩,但其中许多挂钩都有一些细微的损坏。我检查的前三个都是错误的:一个有与您相同的问题(不读取stdin),两个读取stdin,但检查了以
master
结尾的引用,这意味着如果我有:

git push origin sneaky/master
他们会把我的分支
鬼鬼祟祟的/master
当作普通的老分支
master
来对待。此外,任何以
master
命名或结尾的引用(包括标记)都会做同样的事情。当然,创建名为
master
的标记通常是非常有害的,但是为什么要草率呢?拥有一个
refs/notes/master
是非常合理的,并且会破坏这些部署脚本

解决这个问题也不难:只需确保引用名称以
refs/heads/
开头,然后以所需的分支名称结束即可。例如:

while read ohash nhash refname; do
    case "$refname" in
    refs/heads/master) deploy master $ohash $nhash;;
    refs/heads/test?) deploy ${refname#refs/heads/} $ohash $nhash;;
    # ignore all others
    esac
done
(其中
deploy
是一个合适的shell函数)

如果您确实只想要最后一个分支(忽略标记和注释),尽管:

其中“deploybyhash”做的是显而易见的事情。(这是一件非常奇怪的事情,我把它留给您来实现它,并确定它何时是一个特别糟糕的主意;请参见下一个部署示例。)

真正棘手的部分是一个好的多分支部署函数。这一点未经测试,但可能是正确的:

# deploy - deploy a branch to a per-branch deployment area
# arguments: $1 - branch name, $2 - old hash, $3 - new hash
deploy() {
    local branch=$1 ohash=$2 nhash=$3 op tree

    if expr $ohash : '00*$' >/dev/null; then
        op=create
    elif expr $nhash : '00*$' >/dev/null; then
        op=delete
    else
        op=update
    fi
    # if creating or deleting a branch, probably should
    # not do anything here
    if [ $op != update ]; then
        echo $op branch $branch - no deployment action
        return
    fi
    # check whether there's a place to deploy this branch
    tree=/path/for/deployment/$branch
    if [ -d $tree ]; then
        # set up a per-branch index, except maybe for master
        # (this does it for all deployed branches)
        export GIT_INDEX_FILE="$GIT_DIR/index.$branch"
        # if there's no index yet, create it from the tree
        [ -f "$GIT_INDEX_FILE" ] || git --work-tree=$tree reset
        # and check out the appropriate commit w/o changing HEAD
        git --work-tree=$tree read-tree --reset -u $nhash
        unset GIT_INDEX_FILE # clean up after ourselves
    else
        echo "deployment tree $tree is missing, not checking it out"
    fi
}
它可以做得更华丽一些,但它可以做一些关键的事情:

  • 当然,我们需要多个部署区域(
    $tree
  • 由于有多个部署分支,我们必须使用多个索引文件,否则每次都要重建索引。此代码为每个部署区域使用一个索引(
    $GIT\u index\u FILE
  • 在更新非
    主目录
    树时,最好不要改变HEAD,这样我们就避免了
    git签出
    。使用
    git read tree--reset-u
    从指定的提交散列更新我们的索引和工作树
  • 如果分支本身刚刚被删除,我们将无法签出任何内容。如果它刚刚创建,那可能没问题:这是您可能需要调整的内容。例如,您可能需要为这种情况创建树。因此,您可能希望在删除分支时删除部署树。这样做的地方和方法应该是显而易见的

我可以指定要处理的分支吗?当然,就像硬编码一样,将一个特定的分支和过程简化。看看我的第一个代码片段,它读取
stdin
:它检查名为
master
test
的分支以及任何单个字符。但是,如果要将多个分支部署到多个目录,则需要小心使用索引,因为服务器端裸存储库仍然只有一个标准索引,并且计划部署到两个(或更多)目录。
# deploy - deploy a branch to a per-branch deployment area
# arguments: $1 - branch name, $2 - old hash, $3 - new hash
deploy() {
    local branch=$1 ohash=$2 nhash=$3 op tree

    if expr $ohash : '00*$' >/dev/null; then
        op=create
    elif expr $nhash : '00*$' >/dev/null; then
        op=delete
    else
        op=update
    fi
    # if creating or deleting a branch, probably should
    # not do anything here
    if [ $op != update ]; then
        echo $op branch $branch - no deployment action
        return
    fi
    # check whether there's a place to deploy this branch
    tree=/path/for/deployment/$branch
    if [ -d $tree ]; then
        # set up a per-branch index, except maybe for master
        # (this does it for all deployed branches)
        export GIT_INDEX_FILE="$GIT_DIR/index.$branch"
        # if there's no index yet, create it from the tree
        [ -f "$GIT_INDEX_FILE" ] || git --work-tree=$tree reset
        # and check out the appropriate commit w/o changing HEAD
        git --work-tree=$tree read-tree --reset -u $nhash
        unset GIT_INDEX_FILE # clean up after ourselves
    else
        echo "deployment tree $tree is missing, not checking it out"
    fi
}