git post-receive hook似乎没有处理其他分支

时间:2017-03-26 04:28:55

标签: git

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

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

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

git push beta Angular 

它确实将更新推送到存储库,但现在工作目录不受影响。工作目录仍显示master分支的更改。

这些是我收到后挂钩的内容:

#!/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)是否有任何配置指定默认情况下只使用master命令处理git --work-tree分支?

3)无论如何可能硬编码要写入work-tree的分支?因为我可能只会将分支推送到beta.git,并且几乎总是将另一个分支推送到live.git

1 个答案:

答案 0 :(得分:0)

  

有人可以帮我理解如何制作它,以便无论推送哪个分支,它只是根据推送的最后一个分支更新工作目录中的文件?

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

git push origin branch1 branch2 branch3

?你想要部署哪个分支,因为我只用一次推送更新了三个分支?

无论如何,答案有点复杂。部分内容非常简单:任何后接收挂钩都可以,而且大多数应该从标准输入中读取每一行。每个这样的行充当指令,如the githooks manual中所述。输入格式与the pre-receive hook相同,因此请阅读该部分。

你可以通过google search找到许多后接收部署挂钩,但其中很多都是破坏的 - 有点巧妙。我检查的前三个都是错的:一个有你的问题(不读stdin),两个读stdin但检查引用 master结尾,这意味着如果我做的:

git push origin sneaky/master

他们会将我的分支sneaky/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函数)。

如果你真的只想要最后 分支(忽略标签和注释),那么:

update=  # by default, nothing
while read ohash nhash refname; do
    case "$refname" in
    refs/heads/*) update=$nhash;;
    # ignore all others
    esac
done
if [ -n "$update" ]; then deploybyhash $update; fi

where&#34; deploybyhash&#34;这是显而易见的事情。 (这是一个非常需要的奇怪的东西,我留给你实现它 - 并弄清楚它何时是一个特别糟糕的主意;请参阅下一个部署示例。)< / p>

真正棘手的部分是一个很好的多分支部署功能。这个是非常未经测试的,但可能是正确的:

# 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_INDEX_FILE)。
  • 在更新非master树时,最好不要更改HEAD,因此我们避免使用git checkout。使用git read-tree --reset -u从指定的提交哈希中更新索引和工作树。
  • 如果分支本身刚被删除,我们无法检查任何内容。如果它刚刚创建,那可能没问题:这是您可能想要调整的内容。例如,您可能想要为此案例创建树。您可能希望在删除分支时删除部署树。这样做的地方和方法应该是显而易见的。