验证是否在主分支中完成了一个标签

8 浏览
0 Comments

验证是否在主分支中完成了一个标签

在我正在进行的项目中,我们根据标签进行部署。虽然标签必须针对主分支进行(在合并发布后),但有时会有人错误地针对开发或发布分支打标签,这是不正确的。这会导致一些问题。\n在我们的部署脚本中,有一个步骤是从Git中克隆特定的标签,使用的过程类似于这个问题中描述的过程:Download a specific tag with Git\n

$ git clone
$ git checkout tags/

\n我该如何修改这个脚本来检查该标签是否确实是针对主分支进行的?如果不是主分支,我希望停止部署并抛出错误。\n谢谢。

0
0 Comments

问题的出现原因:

在使用Git进行版本控制时,我们经常会在代码库中打上标签(tag)来标记特定的版本。而有时候,我们需要验证一个标签是否在主分支(master branch)上进行了打上。

解决方法:

我们可以使用以下命令来验证一个标签是否在主分支上进行了打上:

git branch -a --contains <tag_name> | grep master | cut -d/ -f3

在这个命令中,我们使用了以下几个命令和操作符来完成验证:

- git branch -a --contains <tag_name>:这个命令会列出包含指定标签的所有分支。其中-a选项表示列出所有分支(包括远程分支),--contains选项表示只列出包含指定标签的分支。

- grep master:这个命令会过滤出包含“master”的分支。我们只关心主分支,所以只保留包含“master”的分支。

- cut -d/ -f3:这个命令会提取出分支的名称。由于git branch -a --contains命令的输出结果是“remotes/origin/master”,我们只需要提取出“master”这部分即可。

通过以上命令的组合,我们可以得到一个结果,如果结果不为空,则说明指定的标签在主分支上进行了打上。

示例:

假设我们要验证的标签是“v.1.2.3”,我们可以使用以下命令来进行验证:

git branch -a --contains v.1.2.3 | grep master | cut -d/ -f3

如果命令的输出结果为“master”,则说明标签“v.1.2.3”在主分支上进行了打上。如果输出结果为空,则说明标签不在主分支上进行了打上。

通过以上的方法,我们可以方便地验证一个标签是否在主分支上进行了打上,从而确保版本控制的准确性和可靠性。

0
0 Comments

问题的出现原因是需要验证一个标签是否在主分支(master branch)中,但是没有提供直接的命令或方法来执行此操作。解决方法是使用git命令来检查主分支是否包含指定的标签。

对于轻量级标签,可以使用以下命令来验证:

git branch --contains $(git rev-parse your-tag) | grep '^* master$'

对于带注释的标签,可以使用以下命令来验证:

git branch --contains $(git rev-list -n 1 your-annotated-tag) | grep '^* master$'

如果标签所指向的提交在主分支中,结果不应为空。可以甚至测试grep的退出码,如果在主分支中则返回0,否则返回1。

需要注意的是,如果分支名称中包含字符串master,上述命令可能会失败。可以使用以下命令来解决此问题:

git branch --contains $(git rev-parse your-tag) | grep ' master$'

在进行最终编辑之前,接受的答案可能与上述解决方法不一致。根据意图,应该接受这个答案作为正确答案。

实际上,grep '^master$'无法找到master分支,因为在master之前有一个空格,所以应该使用git branch --contains $(git rev-parse your-tag) | grep ' master$'来解决此问题。

0
0 Comments

验证标签是否在主分支中完成的原因是因为Git标签或分支名称只是标识一个特定的提交。分支名称的期望效果是标识一个分支的末端提交,该提交随时间而变化,因此它所标识的特定提交也随时间变化。标签名称的期望效果是永远标识一个特定的提交,而不会发生变化。因此,如果有人给主分支打上标签,那么在某些时间点上,解析名称"master"将产生提交哈希"H",解析标签名称也将产生提交哈希"H"。

解决这个问题的方法是使用以下代码进行验证:

if test $(git rev-parse master) = $(git rev-parse $tag^{commit}); then
    echo "master and $tag both identify the same commit"
else
    echo "master and $tag identify two different commits"
fi

这个测试在主分支名称"master"前进之前是有效的。如果我们按照我在StackOverflow上通常使用的方式绘制Git提交图表,可以看到:

tag

|

v

...--o--o--H <-- master

/

...--o--o <-- develop

当前,名称"tag"和"master"都标识提交H,它是一个合并提交。然而,一旦有人在"master"上创建了一个新的提交,图表就变成了:

tag

|

v

...--o--o--H--I <-- master

/

...--o--o <-- develop

现在,"master"标识新的提交"I",所以执行"rev-parse tag^{commit}"将找到"H",而执行"rev-parse master"将找到"I",它们将不相等,并且测试将失败。

Philippe的答案有两种形式,并回答了一个稍微不同的问题。由于分支名称会随时间变化,我们可以使用"git branch --contains"来找到使标记的提交可达的所有分支名称,并查看其中是否有"master"。这将对上面的情况给出一个真/是的答案。不幸的是,它也会告诉你标签"error"包含在"master"中,这是正确的!对于这个图表:

tag

|

v

...--o--o--H <-- master

/

...--o--G <-- develop

^

|

error

这是因为标签"error"标识提交"G",而提交"G"可以从提交"H"(通过跟随提交"H"的第二个父提交)到达。实际上,沿着底部一行的任何标签,指向"develop"分支中包含的任何提交,都标识了"master"分支中包含的提交,因为"develop"分支上的每个提交也都在"master"分支上。

判断任何给定标签所指向的提交是否在只在第一父提交链上出现的"master"的历史记录中有一种方法。这并不是最好的方法,但我们可以使用"git rev-list --first-parent"来枚举从名称"master"可达的所有提交,仅遵循第一个父提交。然后,我们只需检查标记的提交是否在该列表中。以下是一种明确说明我们正在做什么的不好方法:

tagged_commit=$(git rev-parse $tag^{commit}) ||
    fatal "tag $tag does not exist or does not point to a commit object"
found=false
for hash in $(git rev-list --first-parent master); do
    test $hash == $tagged_commit && found=true
done

为了使这个过程更快,最好将"git rev-list"的输出通过管道传递给一个搜索"$tagged_commit"的"grep"命令(由于我们只关心状态,所以将grep的输出丢弃):

if git rev-list --first-parent master | grep $tagged_commit >/dev/null; then
    echo "$tag points to a commit reachable via first-parent from master"
else
    echo "$tag does not point to a commit reachable via first-parent from master"
fi

例如。这里的一个缺点是"git rev-list"将运行直到遍历完所有可达的提交;在一个大型仓库中,这可能需要几秒钟的时间。

0