合并后标记删除后不一致

Inconsistency after tag delete after merge

我在我的 DEV 分支上创建了一个标签。我将这个标签合并到我的主分支中。 意识到标签在 master 分支中更有意义,我删除了标签。

DEV 分支仍然与 master 分支合并,但令我惊讶的是,master 分支不包含来自 DEV 的任何更改。

这里的截图是我重新创建并再次推送标签后截取的,主分支仍然没有任何变化。我也尝试过但未能恢复合并...

对于Git,合并成功,所以我无法将DEV重新合并到master中。 我该如何解决?

[注意:这不是一个完整的答案,但不适合作为评论。]

您的问题始于一个基本的误解:标签根本不附加到分支;他们只指向一个提交。

标签只是一个特定提交(一个提交的 SHA-1)的永久1 名称。请记住,git 在内部通过 SHA-1 识别所有内容,并且引用名称(主要是分支和标签,尽管还有其他形式)部分 2 用于让我们puny humans 处理 SHA-1。

Git 命令(在本例中为 git merge)采用分支和标记名称,通常会将名称转换为 SHA-1,并使用 SHA-1 执行大多数操作。在 git merge 的特定情况下,唯一保留您传入的原始名称的部分是最终提交消息(在本例中为 "Merge tag '20150302-3.2.2015.10'")。其他一切都使用底层 SHA-1。这意味着如果您稍后 将标签从一个 SHA-1 移动到另一个 SHA-1,那根本不会影响合并,它只会让下一个弱小的人感到困惑。

造成混淆的部分原因是标签应该是永久性的。在git中,你有两种常用的名字,branches和tags,它们都是SHA-1s的名字;但它们具有不同的属性。分支名称具有 moving 的 属性,因此它指的是最新的提交。事实上,这非常有用,git 会 自动为您移动它 (在正确但非常常见的条件下)。也就是说,如果你是 "on branch master" 或其他什么,正如 git status 所说的那样,并且你进行了新的提交,那么分支 master 会被调整,以便它指向你刚才的新提交制成。树枝是这样生长的。

相比之下,标签是不会改变的,git 不会自行改变它们​​。您当然可以强制更改或完全删除标签(然后根据需要重新标记或不重新标记)。但是,如果其他任何人——我们存储库的另一个 git 克隆,或者甚至你自己明天或下周或其他任何人——已经将标记记录为指向提交 1234567 之前,现在遇到标记指向提交 6789abc,那可能会很混乱。分支预计会移动,所以如果分支过去指向 1234567,现在指向 6789abc,这似乎很正常;但标签不是,所以这是一个惊喜。

简而言之,移动标签有点粗鲁:对 reader 有点震惊。无论如何,有时它是合适的,但通常最好避免它。

None 这与您当前的问题有任何关系,回顾一下,是这样的:

the master-branch doesn't contain any changes from DEV.

评论者Dropped.on.Caprica, which is that you subsequently reverted your merge. Your commentary answer indicates that you attempted to revert the revert by repeating the git merge command. That won't work as git merge uses the commit graph to decide what work needs to be done, and according to the graph, no work needs to be done after all. See the linked answer了解详情。

要恢复合并,只需revert即可;或者,如果您想重复合并(并且可能以不同的方式进行),您可以使用相同的 git 图节点(或不同但附近的节点)。例如,您可以将一个新的分支名称附加到图中第三次提交的第一个父级。我看不到提交消息,也看不到此提交的 SHA-1,但我可以给你一个相对名称(它只在当前提交更改之前有效):

git checkout -b newbranch HEAD~3

然后从那里合并当前 DEV 分支的提示提交:

git merge DEV

如果您喜欢生成的树,但希望将其作为分支 master 上的 "fast-forward-able" 提交,也有多种方法可以获得它。例如,参见 How to create copy of a snapshot (commit) in a branch onto another branch in git?


1嗯,意味着是永久的。请参阅后续段落。

2它们还用于一种廉价的安全性,因为一些出口商只允许通过参考名称访问 SHA-1。但是,其他导出机制通常会违反这一点:例如,如果您向它们提供正确的 SHA-1,许多 Web 服务器将吐出一个 git 对象。

也许最重要的是,引用是使提交——所有 git 对象,真的——可访问的东西。 可达的对象——可以通过 SHA-1 找到的对象,而不是从名称到 ID 映射开始然后跟随那里的其他 ID 有资格 "garbage collection" 并最终从存储库中删除。