修复git标签?

修复git标签?,git,Git,我刚才做了以下工作: // make change // git add . // git commit -m "2.0.0" // git tag -a v2.0.0 <sha-of-above-commit> // git push --tags //进行更改 //git添加。 //git提交-m“2.0.0” //git标签-a v2.0.0 //git推送标签 但是,我忘了推送实际的提交,现在我的标记没有显示(大概是因为我没有实际推送我标记的提交) 然后我重新克隆了rep

我刚才做了以下工作:

// make change
// git add .
// git commit -m "2.0.0"
// git tag -a v2.0.0 <sha-of-above-commit>
// git push --tags
//进行更改
//git添加。
//git提交-m“2.0.0”
//git标签-a v2.0.0
//git推送标签
但是,我忘了推送实际的提交,现在我的标记没有显示(大概是因为我没有实际推送我标记的提交)

然后我重新克隆了repo,运行了git标签,并在那里看到了我的标签

但是,我的提交没有列在
git log
下。因此,我重新做了更改,并运行了gitpush。这是成功的。但是,
git push--tags
失败了,因为它说远程设备上已经存在该标记

有什么解决办法吗?我试图删除远程v2.0.0标记,但得到了一个
(钩子被拒绝)
错误。

TL;DR:
git推送原始主机
答案正确:您的
gitpush
推送了提交和标记,但另一个(远程)git存储库中没有包含提交的分支。也就是说,就您自己的Git提交图而言,这里有我要猜测的分支是
master
——这是:

...--o     <-- origin/master
      \
       o   <-- master, tag:v2.0.0
现在从其他Git克隆存储库的任何人,包括您自己,都会在
Git标记
输出中看到标记,但不会在分支
master
上看到提交,因为它不在分支
master
上。指向新提交的唯一链接是标记

解决方案很简单:执行一次
git推送
,让您的git请求他们(源站)的git将其分支
master
设置为指向新提交。例如,如果提交的散列ID是
1234567
,则可以执行以下操作:

git push origin 1234567:master
甚至从你的新克隆。或者,由于标记
v2.0.0
解析为正确的提交散列:1

不过,这个简单修复程序的最简单版本是从原始开发存储库执行
push
操作,其中
master
分支指向与
v2.0.0
标记相同的提交。在这种情况下,不需要指定refspec参数的两半:

git push origin master
(当然,这是假设自这一点以来,origin上的
master
没有增加新提交)


1我说“resolves to”,然后介绍这个时髦的
v2.0.0:^{commit}
语法。这是怎么回事

由于
v2.0.0
是一个带注释的标记(由
git-tag-a
制成),因此名称本身实际上指向存储库中的标记对象。它是指向提交的标记对象。当我绘制提交图时,我绘制的是提交图,而不是提交和标记图。:-)所以我略去了这一点

但是,当我们转到git push时,最好让他们的git将其分支
master
设置为直接指向提交,而不是指向标记。不允许分支名称指向标记。也许请求会起作用也许Git会知道“不允许分支名称指向标记”,并会使用适当的魔法将标记对象转换为其目标提交ID,但也许不会。我们可以通过告诉Git将任何标记名转换为其目标提交来完全避免这个问题

这就是这个时髦的语法所做的。如中所述,
name:^{type}
告诉Git首先解析名称,然后根据需要“剥离”该名称以查找给定类型的Git对象

当您给Git一个分支名称时,该名称保证解析为提交对象,因为分支名称必须指向提交对象。另一方面,标记名可以指向任何Git对象,包括提交、标记、树或blob。通常它们只指向标记对象或提交对象,但Git不会阻止您创建指向blob或树的对象。我在自己的存储库中为各种实验目的做了这些。因此,对于标记,可以使用
^{commit}
强制将其解析为提交。如果名称指向带注释的标记对象,则会跟随该标记进行提交。如果名称已指向提交,则它不执行任何操作。如果名称以某种方式指向树或blob,则会产生错误

您还可以使用
:^{tree}
:^{blob}
验证名称是否指向树或blob对象。当然,如果名称是一个分支名称,则它不是,但是
名称
部分也可以包括一个路径:例如,
master:Documentation
在Git自身的Git存储库中为分支
master
中的树对象命名,如果您正在编写脚本,并且需要确实确保获得树的哈希ID,你可以写:

treehash=$(git rev-parse master:Documentation^{tree}) || die ...

在您的脚本中。

“可能是因为我没有实际推送我标记的提交”—这不重要。您不能推送悬挂的引用。您确定远程标记确实存在吗?您如何尝试删除该标记,并且您的服务器通常不允许删除标记?(另外,如果
git log v2.0.0
显示您的提交,并且它是您想要的提交,您可以将它推送到任何一个分支。)尝试使用
git push删除标记--delete origin v2.0.0
。不确定我的服务器是否一般不允许删除标记,但可能?标记也是一个引用。当推送标记时,它指向的提交以及仅存在于本地的提交的父级都会被推送。因此,在克隆之后,应该会看到通过git log v2.0.0进行提交。仅仅
git log
不是正确的命令,因为它列出了当前签出的分支的日志,很可能是
master
。如果
v2.0.0
master
发生分歧,您将无法在
master
的日志中看到标记的提交。
git push origin master
treehash=$(git rev-parse master:Documentation^{tree}) || die ...