【问题标题】:Will tag referencing commits unreachable from any branch be lost?从任何分支无法访问的标记引用提交是否会丢失?
【发布时间】:2026-02-02 02:15:01
【问题描述】:

我在分支 branch 上处理我的项目。然后我恢复使用

git revert tag-name

然后我取得了一些进展并承诺。当我尝试推送时,出现此错误:

更新被拒绝,因为遥控器包含您所做的工作 本地没有

我不想在恢复之前丢失我的进度,但想从branch 中删除之后所做的提交,让它们在1.00.00rcXX 标记下可供将来参考。

我创建了一个存储库的克隆,在那里标记了branch 的头部,并将branch 倒回到还原提交:

git tag -a 1.00.00rcXX -m message
git reset --hard HEAD~1 # remove last commit from current branch

现在我想强制将我的更改推送回我的原始存储库,因此branch 之前的所有提交都将丢失。

我的标签也会丢失吗,因为它是基于无法从branch 访问的提交?

【问题讨论】:

  • @Palec 我确实想在还原之前丢失所有提交。而且我还想将它们保存在标签上以供将来参考。但我当然不想在还原之前合并任何提交,这就是我强制推送的原因。
  • 再次阅读您的问题,我想我终于明白了您想要表达的意思。您在存储库中进行了还原和后续更改,然后克隆了此存储库,只是为了在克隆中创建 1.00.00rcXX 标记。对吗?
  • “标签将使这些提交保持活跃”这回答了我的问题。你确定这是真的吗?
  • 我发布了一个答案。现在我正在考虑编辑你的 Q 以便在没有这个评论线程的情况下有意义。这一系列事件是否等同于发生在你身上的事情? git clone 'git://some.remote/repos' projectgit checkout branch; git revert tag-name; some-work; git tag -a 1.00.00rcXX -m message; git reset --hard HEAD~5 现在 branch 与紧跟在 git revert tag-name 之后的相同。在这一刻,您要问是否可以安全地强制推送branch 而不会丢失1.00.00rcXX 标签引用的历史记录。
  • 编辑了您的问题,以便对未来的访问者更有意义。如果我有任何问题,请随时澄清。

标签: git git-push git-tag


【解决方案1】:

不可达性和垃圾回收

只有真正无法到达的提交才能被垃圾收集,从而永远丢失。

引用man gitglossary:

无法到达的对象

无法从分支、标签或任何其他引用访问的对象。

只要标签存在,它所链接的历史部分就被认为是可达的,因此不会被垃圾回收。标签使这些提交保持“活跃”。

推送标签和强制推送分支是安全的

Git 试图阻止您在任何分支中进行非快进更改。您必须将-f 选项传递给git push 才能在重置(回绕)分支后执行推送。如果你记住implications of overwriting history,你可以同时推送引用分支原始状态的标签和分支的新头部,你不会丢失任何东西。

运行这个:

git push --tags
git push -f origin your-rewound-branch

最好使用分支而不是标签

顺便说一句,对这样的事情使用标签可能不是一个好主意。可能有一天你会想要删除开发历史的死胡同部分,你不应该对标签做这件事。使用分支(头部)而不是标签更适合这样的目的。只需使用(也许使用更具描述性的名称)

git branch 1.00.00rcXX

而不是

git tag -a 1.00.00rcXX -m message

【讨论】: