运行以下步骤后,出现以下错误:
To git@provider.com:username/repo-name.git
! [rejected] dev -> dev (already exists)
error: failed to push some refs to 'git@provider.com:username/repo-name.git'
hint: Updates were rejected because the tag already exists in the remote.
1.已创建存储库
1.已将存储库克隆到本地计算机上。
1.已修改README文件,已提交更改并已推送提交。
1.已创建标记dev
:git tag dev
1.推入的标记:git push --tags
1.已修改README文件,已提交更改并已推送提交。
1.已删除标记dev
,再次创建并推送标记:
git tag -d dev
git tag dev
git push --tags
为什么会这样?
我用的是Mac。我的朋友用的是Linux(Ubuntu),没有这个问题。我知道我可以用git push --tags -f
来强制标签更新,但这是危险的(例如,只在标签中重写错误的提交,而不是在分支中)。
9条答案
按热度按时间lrpiutwd1#
编辑,2016年11月24日:这个答案显然很流行,所以我在这里添加一个注解。如果你 * 替换 * 中央服务器上的一个标记,任何拥有 * 旧 * 标记的人--任何已经拥有该标记的中央服务器存储库的克隆--都可以 * 保留其旧标记 *。因此,尽管这告诉了你如何去做,你需要让每个已经有“错误”标签的人删除他们的“错误标签”,并用新的“正确标签”来代替。
在Git 2.10/2.11中的测试表明,对于运行
git fetch
的客户端,保留旧标签是默认行为,而对于运行git fetch --tags
的客户端,更新标签是默认行为。(原文如下。)
当你请求推送标签时,
git push --tags
会向远程服务器发送一个*new-sha1* refs/tags/*name*
形式的更新请求(沿着任何提交和其他所需的对象,以及来自推送设置的任何其他ref更新)。每个标签一个。)更新请求由远程修改以添加 *
old-sha1
*(或者同样,每个标签一个),然后被传递到预接收和/或更新钩子(远程上存在的任何钩子)。如果正在创建标记,则 *
old-sha1
* 值为全零“空”SHA-1。如果正在删除标记,则 *new-sha1
* 为空SHA-1。否则,两个SHA-1值都是真实的的有效值。即使没有钩子,也有一种“内置钩子”可以运行:除非您使用“force”标志,否则遥控器将拒绝移动标记(尽管“内置钩子”对于“add”和“delete”总是可以的)。您看到的拒绝消息来自这个内置钩子。(顺便说一句,这个内置钩子也拒绝不是快进的分支更新。)1
但是,这里有一个了解发生了什么的关键-
git push
步骤不知道远程设备现在是否有那个标签,如果有,它有什么SHA-1值。它只说“这是我的完整标签列表,沿着它们的SHA-1值”。远程设备比较这些值,如果有添加和/或更改,就在这些值上运行钩子。(对于相同的标签,它什么都不做。对于你没有的标签,它也什么都不做!)如果你在本地删除了标签,那么
push
,你的push就不会传输标签,远程服务器会假设不需要做任何修改。如果你在本地删除了标签,然后创建一个指向新位置的标签,那么
push
,你的推送会传输标签,远程会将其视为标签更改并拒绝更改,除非它是强制推送。因此,您有两个选项:
后者 * 可以 * 通过
git push
2实现,即使在本地删除标签和push
命令没有任何效果。假设远程的名称是origin
,而您希望它删除的标签是dev
:这将要求远程删除标记。本地存储库中是否存在标记
dev
是无关紧要的;这种push
(以:*remoteref*
作为refspec)是纯删除推送。遥控器可能允许也可能不允许删除标记(取决于是否添加了额外的钩子)。如果允许删除,那么标签将消失,当你有一个本地的
dev
标签指向某个commit或带注解的标签repo对象时,发送第二个git push --tags
标签。在远程,dev
现在是一个新创建的标签,所以远程可能会允许推送(同样,这取决于添加的任何额外钩子)。force-push更简单,如果你想确保除了标签之外不更新任何东西,只要告诉
git push
只推送一个refspec:(note:如果只显式推送一个标记ref-spec,则不需要
--tags
)。1当然,这个内置钩子的 * 原因 * 是为了帮助强制执行同一远程存储库的其他用户所期望的行为:分支不会回滚,标签也不会移动。如果你强制推送,你应该让其他用户知道你在做这个,这样他们就可以纠正它。注意,“标签根本不会移动”是Git 1.8.2新强制的;以前的版本允许标记在提交图中“向前移动”,就像分支名称一样。参见git 1.8.2 release notes。
2如果你能登录到远程设备,这就很简单了。只要进入Git存储库并运行
git tag -d dev
。注意,无论是删除远程设备上的标记,还是使用git push
删除它,在一段时间内,任何访问远程设备的人都会发现dev
标记丢失了。(如果他们已经有了旧标签,他们将继续拥有 * 他们自己的 * 旧标签,他们甚至可能在您推送新标签之前将 * 他们的 * 旧标签推回。)dgtucam12#
仅在Mac SourceTree中取消选择推送所有标签复选框:
w6lpcovy3#
如果您使用SourceTree,这非常简单。
x1c 0d1x基本上,您只需要删除并重新添加冲突的标记:
1.转到选项卡存储库-〉标记-〉删除标记
1.选择冲突的标记名称
1.选中从所有遥控器中删除标记
1.按删除
1.创建与正确提交同名的新标记
1.将更改推送到远程时,请确保选中推送所有标记
k2fxgqgv4#
看来我在这个问题上迟到了和/或它已经得到了回答,但是,可以做的是:(在我的例子中,我在本地只有一个标签,所以..我删除了旧标签,并重新标记为:
然后道:
这将更新远程上的所有标记。
可能有危险!使用风险自负。
cxfofazt5#
如果要UPDATE一个tag,我们可以说它是
1.0.0
git checkout 1.0.0
1.* 进行更改 *
git ci -am 'modify some content'
git tag -f 1.0.0
1.删除github上远程标记:
git push origin --delete 1.0.0
git push origin 1.0.0
已完成
dfty9e196#
您被拒绝的原因是您的tag与远程版本失去了同步。这与分支的行为相同。
通过
git pull --rebase <repo_url> +refs/tags/<TAG>
从远程与标签同步,同步后,您需要管理冲突。如果您安装了diftool(例如,meld)git mergetool meld
,请使用它来同步远程并保留您的更改。使用**--rebase**标记进行拉操作的原因是,您希望将您的工作放在远程工作的顶部,这样可以避免其他冲突。
另外,我不明白的是为什么你要删除
dev
标签并重新创建它???标签用于指定软件版本或里程碑。例如git标签v0.1dev
,v0.0.1alpha
,v2.3-cr
(cr -候选版本)等等。另一种解决方法是发出一个
git reflog
并转到你在remote上推送dev
标签的时刻。复制 commit id 和git reset --mixed <commmit_id_from_reflog>
,这样你就知道你的标签在你推送它的时刻与remote是同步的,不会产生冲突。hsgswve47#
在Windows源目录树中,取消选中
Push all tags to remotes
。tnkciper8#
这里有一些很好的答案。特别是the one by @torek。我想我应该为那些匆忙的人添加一点解释。
总而言之,当你在本地移动一个标签时,它会把标签从一个非空的提交值改变为另一个值。然而,由于git(默认行为)不允许改变非空的远程标签,所以你不能推送改变。
解决方法是删除标记(并删除所有远程)。然后创建相同的标记并推送。
e5nszbig9#
虽然我还在想我是怎么进入这种状态的。我找到了一个简单的解决办法-删除所有本地重复的标签,然后从远程拉那些标签。例如:
不再有恩怨或警告。
您可能需要考虑提前备份本地存储库。