在我正在做的这个项目中,我们基于标签进行部署。虽然标签必须针对master分支进行(在您合并发布之后),但有时候错误地有人可以针对dev或release分支进行标签,这是不正确的。这会导致几个问题。
在我们的部署脚本中,有一个步骤,我们从git克隆一个特定的标签,使用类似于这个问题中描述的过程:Download a specific tag with Git
$ git clone
$ git checkout tags/<tag_name>
我如何修改这个脚本来检查这个标记是否真的是针对master分支完成的?如果分支不是master分支,我想停止部署并抛出一个错误。
- 谢谢-谢谢
4条答案
按热度按时间gywdnpxw1#
git分支-a --包含|grep主机|切割-d/ -f3
示例:git分支-a --包含v.1.2.3| grep主机|切割-d/ -f3
pgky5nke2#
简而言之,你不能。至少事后不能。
你可以做的就是创建一个 annotated tag。这会在tag上放置一个消息。然后这个消息可以包含当前 checkout 分支的分支名称。然后你可以检查这个消息是否包含
master
。另一个解决方案是使用
pre-push
commit钩子来检查要推送的任何新标签是否可以从master
分支到达。这两种解决方案都需要在客户端进行设置,因此可能会被愚蠢或恶意的用户绕过或禁用。
如果你可以控制你的Git仓库管理器,你可以考虑为相同的可达性标准进行预接收钩子测试。
我的建议是找出正确的方法来自动化您的释放标记过程。
祝你好运!
flmtquvp3#
正如一些人所指出的,你的问题在重新表述之前无法得到真正的回答。这是因为Git标签或分支名称只是标识 * 一个特定的提交。* 分支名称的预期效果是标识分支的 tip 提交,它会随时间而变化,因此它标识的特定提交也会随时间而变化。标签名称的预期效果是永远标识一个特定的提交,因此,如果某人标记了
master
,在某些时刻,解析名称master
会产生提交哈希 H,解析标签名称 * 也 * 会产生提交哈希 H:这个测试一直有效,直到有人把分支名称
master
设置为advance,之后它就不再有用了。如果我们用我在StackOverflow上绘制Git提交图的方式来绘制,我们可以看到:目前,
tag
和master
都标识提交H,这是一个合并提交。但是,一旦有人在master
上创建了一个 * 新 * 提交,图表就会变成:现在
master
标识新提交I
,因此执行rev-parse tag^{commit}
将找到H
,而执行rev-parse master
将找到I
,它们将不相等,测试将失败。(我在这里把
I
作为一个普通的提交,但它也可能是一个带有第二个父提交的合并提交。如果是这样,想象第二个向后指向的线/箭头从I
出现,指向其他更早的提交。Philippe's answer有两种形式,并且回答了一个稍微不同的问题。由于分支名称 * 会 * 随着时间的推移而移动,我们可以使用
git branch --contains
来查找 * 所有 * 使标记提交可达的分支名称,并查看其中是否有一个是master
。对于上面的情况,这将给予正确/是的答案。不幸的是,它还将告诉您标签error
包含在master
中-这是真的!-对于 * 这个 * 图:这是因为标签
error
标识提交G
,并且提交G
是从 * 提交H
* 可达的(通过跟随H
的第二父提交)。实际上,沿着底部行指向包含在develop
分支内的任何提交的任何标签标识包含在master
分支内的提交,因为 * 当前在develop
上的每个提交也在master
上 *。(顺便说一句,使用
git rev-parse your-tag
和使用git rev-list -n 1 your-annotated-tag
之间的区别可以通过使用git rev-parse $tag^{commit}
来解决。这里的问题是,带注解的标记有一个实际的存储库对象,类型为“annotated tag”,名称指向该对象;单独使用git rev-parse your-annotated-tag
会找到 tag 对象,而不是它的提交。^{commit}
后缀语法在the gitrevisions documentation中有描述。)有一种方法可以判断任何给定标记所指向的提交是否在
master
的历史记录中,并且只发生在第一个父链上。git branch --contains
和git merge-base --is-ancestor
是用于查找可达性的常用构建块,但是它们都跟随 * 所有 * 父节点。我们需要使用git rev-list --first-parent
来枚举所有从名字master
可以到达的提交,然后我们简单地检查标记的版本号是否在列表中。这里'It“如果我们把自己的工作搞得很清楚,那就不好了:为了更快地完成这一过程,最好将
git rev-list
的输出通过一个grep
来搜索$tagged_commit
(由于我们只关心状态,因此丢弃grep的输出):(这里的一个缺陷是
git rev-list
将一直运行到每个可到达的提交;在大型存储库中,这可能需要 * 秒 *。)e4eetjau4#
如果是轻量型标签:
对于带注解的标记:
如果标记指向的提交位于
master
中,则结果不应为空。(您甚至可以测试grep
的退出代码,如果位于master
中,则返回0
,否则返回1
。)