【问题标题】:git hook to create staging branchgit hook 创建临时分支
【发布时间】:2016-01-11 04:25:06
【问题描述】:

我在 Bitbucket 上托管我的代码。 webhook 不足以解决我的问题,所以我希望 git hooks 能够工作。由于我不认为它们会在服务器端工作,因此应该将 git 挂钩传播到每个开发人员机器上的每个结帐。 (我知道这可能是一个问题,因为它通常是一个本地文件,但我希望可以使用来自here 的信息来解决它)

我想创建一个 git 钩子,它将更改推送到暂存分支。

意思是,如果我是一个名为bob 的用户并且我想推送到production/master,而不是推送到production/master 分支,它将推送到像staging/master/bob 这样的临时分支。另一个用户roy 也一样,他推送到production/master,它将转到staging/master/roy。对于任何生产分支也是如此。所以edd推送到production/2.0会推送到staging/2.0/edd

我已经尝试了 pre-commit 钩子,但我找不到一种方法来引导推送的目标。我知道这是可能的。

我尝试使用GIT_WORK_TREE,但似乎无法正常工作。


澄清

对于bob 开发人员来说,整个过程应该是无缝的。他应该从主人那里拉出来,然后推给主人。 (或他正在处理的任何分支)并且该过程将在后台发生。它将他的更改推送到暂存分支,然后将进行 CI 过程,如果成功将被推送到主分支。这是我需要的解决方案。

【问题讨论】:

    标签: git continuous-integration bitbucket githooks


    【解决方案1】:

    forks 可以更好地解决管理问题:

    通过 fork 一个 repo,bob 可以推送到它而无需重命名分支:master 将位于 bitbucket.org/bob/repo/master

    然后他可以为暂存存储库(它本身是产品存储库的一个分支)创建一个PR (Pull Request),致力于整合开发人员的贡献。

    一旦代码在 staging repo 中按预期运行,就可以对 prod repo 进行 PR(仅由少数人管理)

    该工作流程比试图摆弄分支名称并在一个远程存储库中管理所有内容要容易,因为没有钩子(只有 webhook)。

    【讨论】:

    • 这可以在脚本中自动完成吗?哪里 bob 只需要 pushproduction/master ?这个想法是 bob 不应该为了暂存分支工作而做任何额外的步骤或工作。
    • @InbarRose 不需要脚本:rob 在暂存仓库中直接推送他应该推送的地方。但是还有一个额外的步骤来验证 staging rob 分支到 staging(用于合并所有贡献)然后到 prod 的集成。
    • 请查看我对原始问题的编辑。 “对于 bob 开发人员来说,整个过程应该是无缝的。他应该从 master 中提取并推送到 master。(或他正在处理的任何分支)并且该过程将在后台发生。它将他的更改推送到暂存分支,然后进行CI流程,如果成功将被推送到主分支。这就是我需要的解决方案。”
    • @InbarRose 需要服务器端的 webhook,你提到你不想这样做。我不知道其他方法可以使用客户端钩子(如预提交)建立自动化工作流程。只有服务器端的钩子。
    • 也许我可以让服务器端解决方案工作。你能提供这样的答案,或链接到它吗?
    【解决方案2】:

    您可以使用pre-push 钩子并在其中运行另一个git-push 命令。通过这种方式,您可以更改目标引用,从而在暂存分支上推送数据并中止在生产分支上执行推送。 这是一个脚本的草图:

    #!/bin/sh
    
    #You may want to iterate over all refs 
    #in case there are more branches that are being pushed
    read local_ref local_sha remote_ref remote_sha
    
    #Make sure you are not running the hook ad inifinitum
    [[ $remote_ref =~ .*"staging".* ]] && exit 0
    
    #Make sure these are unique
    name="$(git config --get user.name | awk '{print $1;}' | tr '[:upper:]' '[:lower:]')"
    
    #Compose a staging branch name accordingly
    staging_branch="$(echo "$remote_ref" | sed 's:refs/heads/production/:staging/:')"
    staging_branch="$staging_branch/$name"
    
    git push origin master:"$staging_branch"  
    
    #Don't forget that exit status needs to be != 0
    #unless you want to push the same changes twice
    exit 1
    

    您需要考虑一些更复杂的情况,但我想经过一些调整应该可以工作。

    稍后您可以在 CI 服务器上运行任何您想要的测试,将其推送到生产环境并删除临时分支。 您可能想要配置每个本地存储库,以便 git-fetch 自动修剪:

     git config remote.origin.prune true
    

    这样开发人员就不会看到对远程暂存分支的过时引用(如果您选择删除它们)。

    或者,您可以尝试将 master 的上游设置为适当的暂存分支。但是,如果您删除了远程参考,它可能会变得混乱。

    底线

    我认为这不是最优雅的解决方案,但我相信它可以直接回答您的问题。这种方法的缺点之一是它最终不会以 0 退出。我不知道某些外部工具将如何处理它。当您使用命令行时,它只会生成一个您可以忽略的错误行。

    您可能需要考虑@VonC 的解决方案或其他某种策略,以防止直接推送到生产分支。

    编辑:

    命令行消息如下所示:

    【讨论】:

    • 看起来不错,所以如果我以 0 退出,那么它将继续沿链向下,并进行常规推送,但如果我以其他方式退出,则会显示错误。现在有没有办法告诉它停止其余的过程,但仍然表明一切正常? :(
    • 我添加了一个带有命令行消息的屏幕截图。无论如何都会打印嵌套的成功推送的输出,因此您仍然可以识别是否出现问题。只有一行包含该中止提交的错误消息。如果这不能满足您的需求,我想您可以使用 git 源代码并可能拦截一个特定的退出状态。
    猜你喜欢
    • 1970-01-01
    • 2015-04-06
    • 2010-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-22
    • 1970-01-01
    相关资源
    最近更新 更多