找到最初出现提交的分支(git / Jenkins / CD)

时间:2016-11-08 22:27:21

标签: git jenkins version-control continuous-deployment continuous-delivery

我正在设计一个Jenkins构建系统,当任何标记被推送到repo时触发。从那里,我们想知道标签所引用的提交被推送到哪个分支。从那里,我基于该分支名称启动其他Jenkins构建。除了找出标记了哪个分支外,此管道中的所有内容都很简单。

基本上,我的团队制作了并且目前正在使用productionstaging分支 - 当开发人员将内容合并到productionstaging时,想要发布,他们会标记版本号,然后将其推出。然后,Jenkins可以在生产分支上使用该标记更新生产服务器,并使用标记登台到分段分支。如果master被标记,那么我将启动CI构建和测试。

我一直在这篇博客文章中测试方法:http://johndstein-blog.logdown.com/posts/428667提供以下内容:

export HASH=$(git rev-parse HEAD)
export BRANCH=$(basename $(git branch -r --contains ${HASH}))
export TAG=$(basename $(git describe --all --exact-match ${HASH}))

echo "HASH: $HASH"
echo "BRANCH: $BRANCH"
echo "TAG: $TAG"

但这在100%的时间内都不起作用 - 对于某些回购,当运行第2行(抓取分支)时 - 我得到多个分支,并且它出错了。我对git很新,但据我所知,这是因为提交是在一个分支中进行并合并到另一个分支中。

我的问题是,如果我有标签,我能否可靠地找到最初推送到的分支的名称?而且,这是一种聪明的方式吗?

1 个答案:

答案 0 :(得分:1)

一般情况下这是不可能的。 “最初被推到”甚至没有明确定义,如果没有选择一些“原创”并使其保持原木。

这是一个例子。假设我创建了分支sneakgotcha

     C   <-- sneak
    /
A--B     <-- master
    \
     D   <-- gotcha

现在,如果我git push这些分支中的一个或两个,接收Git存储库将获得两个提交CD以及更新名称refs/heads/sneak的请求和refs/heads/gotcha。到目前为止,一切似乎都很好。但现在我这样做而不是推动,或者在推得足够快之后非常迅速,以至于你无法进入我在做什么:

$ git push origin sneak:sneak gotcha:gotcha &&
> git checkout master &&
> git merge sneak gotcha &&
> git push origin master:master :sneak :gotcha

git merge使章鱼合并(当然我已经安排成功,否则这需要我太长时间来欺骗你:-))。 push步骤然后将提交E发送到服务器,同时请求更新refs/heads/master以指向它,以及删除 refs/heads/sneakrefs/heads/gotcha。结果是:

     C
    / \
A--B---E   <-- master
    \ /
     D

提交和/或推送了哪些分支CD?好吧,在我们覆盖并删除它之前,我们在服务器上有大约6毫秒的信息。

更糟糕的是,我推送的地方可能是推镜,而真正的服务器又回来了。推镜可能有两到三秒钟的信息,有足够的时间来抓取它...但是推镜和真实(终点)服务器之间的链接是起作用,在这三秒钟内我覆盖了它,这样推镜就可以通过一个请求将提交CDE发送到真实服务器更新refs/heads/master以指向提交E

现在,如果我们将“最初推送到”定义为“发送到推送镜像”,我们使推送镜像保留日志,日志将显示我最初要求提交{ {1}}转到C并提交sneak以转到D。假设推送镜像和最终中央服务器之间出现链路断开故障,该日志就是唯一的位置,并带有此信息。你可以安排一个侧面通道来检索这个,但是这些都没有内置到Git中(即使是日志记录也有问题:你可以尝试使用Git的reflogs但是它们可能不够精细,如果你关心多次推送第二,真正严格的订购)。

默认情况下,裸存储库(和推送镜像)不启用Reflog,但您可以使用简单的gotcha启用它们。

所有这一切......

要担心的主要事实是提交可以在零,一个或多个分支上。 1 诀窍是不依赖于分支名称除非你是控制这些名字的人。您可以在git configpre-receive挂钩中对分支名称进行简短的控制,但使用起来很棘手。

最好的办法是不要依赖名称,而是要求一些单独的指示符,例如嵌入在提交消息本身中的字符串(并且您可以使用预接收挂钩来检查这一点)。或者,您可以简单地要求您的标记名称具有明确定义的格式:

post-receive

或其他什么。标签的名称告诉您特定提交的意图是什么,并且完全独立于任何包含分支。

1 提交 no 分支有点不寻常,但很容易创建:只需标记分支提示,然后删除分支名称。您可以推送标记,并使用标记将提交转发到接收服务器,但不使用分支。