为啥合并后GIT会说“已经是最新的”,但分支之间的差异仍然存在?

Posted

技术标签:

【中文标题】为啥合并后GIT会说“已经是最新的”,但分支之间的差异仍然存在?【英文标题】:Why after merge does GIT say "Already up-to-date", but differences between branches still exist?为什么合并后GIT会说“已经是最新的”,但分支之间的差异仍然存在? 【发布时间】:2013-03-22 02:54:44 【问题描述】:

我最初在“newfeature”分支工作,我被要求紧急修复实时分支上的错误。我为名为“generalmaintenance”的分支创建了一个分支,完成了这项工作,然后切换到开发并将其合并。我现在想返回“newfeature”分支并合并我之前合并到其中的更改。

当我切换到'newfeature'并合并到'develop'时,有3个文件发生冲突。

我陷入了解决冲突的纠结中,最终决定使用 Aptana Studio 3(这是我的 IDE)的“团队”菜单中的“恢复”命令。我希望这会让我回到合并之前,它似乎已经完成了。

无论如何,当我再次合并'develop'时,它会显示Already-up-to-date,但是在比较两个分支之间的文件时,它们非常不同,并且我在另一个分支中添加的更改没有被合并。

请问我现在如何合并这两个分支?

【问题讨论】:

【参考方案1】:

恢复合并与重置合并

我猜你实际上是Already-up-to-date

问题在于git revert 不会撤消合并,它只会撤消合并带来的更改。创建合并提交时,您将合并这两个分支的提交历史记录。

合并

     develop
        |
A---B---C
 \       \
  E---F---M
          |
      newfeature

在上面的例子中,develop 被合并到newfeature,创建了M 提交。如果您要运行git log newfeature,您会看到来自两个分支的所有提交,但是从newfeature 分支的角度来看,所有这些更改都是由M 提交执行的。

还原

git revert 命令不会删除任何提交,而是创建一个新的提交来撤消提交所包含的更改。例如,如果您有一个包含此差异的提交...

-This is the old sentence.
+This is the new sentence.

然后将其还原,revert 命令将创建一个新的提交,该提交刚刚执行了相反的差异,它只是翻转了符号。

-This is the new sentence.
+This is the old sentence.

这对于撤消其他开发人员已经拥有的提交造成的损害非常有用。它推动历史前进,而不是改变历史。

还原合并

但是,在非快进合并的上下文中,它可能会产生不良影响。

     develop
        |
A---B---C
 \       \
  E---F---M---W
              |
         newfeature

假设 W 是一个反向提交,你可以看到运行 git log newfeature 仍然会包含来自开发分支的所有提交。因此,来自develop 的其他合并将不起作用,因为它没有看到您的分支中缺少任何内容。

使用git reset 而不是rev​​ert。

将来,如果合并尚未与其他开发人员共享,您可能会考虑使用git reset --hard <ref>(其中<ref> 是合并的提交哈希)撤消合并。在上面的示例中,在创建合并提交 M 后,运行命令 git reset --hard F 将导致以下结果。

     develop
        |
A---B---C
 \       \
  E---F---M
      |
  newfeature

正如您所见,这种技术并没有像某些人认为的那样消除提交,它只是将您的分支移回您选择的提交。现在如果你运行git log newfeature,你只会得到提交FEA。现在合并实际上已从您的分支历史记录中消失,因此稍后尝试在 develop 中重新合并不会导致任何问题。

这种方法并非没有复杂性。意识到您现在正在修改历史记录,因此如果在进行 M 合并之后将 newfeature 分支推送到远程分支,那么 git 会认为您只是过时并告诉您需要运行git pull。如果只是你在那个远程分支上工作,那么请随时 force-push - git push -f <remote> <branch>。这将具有与重置相同的效果,但在远程分支上。

如果这个分支正在被多个开发人员使用,而他们现在已经从中撤出 - 那么这是一个坏主意。这正是git revert 有用的原因,因为它在不更改实际历史记录的情况下撤消更改。

对历史记录使用重置实际上仅适用于尚未共享的提交。

解决方案 - 还原还原。

如果合并提交已经被共享,那么最好的方法可能是在该合并上使用git revert。但是,正如我们之前所说,您不能简单地将分支合并回来并期望该分支的所有更改重新出现。答案是还原还原提交。

假设您在尊重 newfeature 中的合并之后在 develop 分支上做了一些工作。您的历史记录将如下所示。

         develop
            |
A---B---C---D
 \       \
  E---F---M---W
              |
         newfeature

如果你现在将develop 合并到newfeature 中,你只会得到D,因为它是唯一一个不属于newfeature 分支历史的提交。你还需要做的是恢复W commit - git revert W 应该做的伎俩,然后是git merge develop

                 develop
                    |
A---B---C-----------D
 \       \           \
  E---F---M---W---M---G
                      |
                 newfeature

这将恢复原始合并提交所做的所有更改 - 实际上是由 CB 进行但在 W 中恢复的,然后通过新的合并提交 G 引入 D我建议在合并最近对develop 的更改之前 还原revert,我怀疑按此顺序执行此操作会降低触发冲突的可能性。

TL;DR

还原会创建一个“还原提交”。撤消还原时,您需要对第一次还原时创建的还原提交运行还原命令。它应该很容易找到,git 倾向于自动评论恢复,以便它们以“Reverted”一词开头。

git revert <commit>

【讨论】:

非常感谢 Eddie 对此的详细解释 (+1)。将再次研究它以消化它并在接受您的答案之前尝试您的解决方案。我“非常有信心”这将是解决方案。 仅供参考:我进行了一些次要但重要的编辑以纠正一些事情。最重要的是,我更正了关于恢复合并提交的示例。它是git revert M,我将其更正为git revert W。此外,第二个差异是错误的。解释还原提交的那个。修正了 +/- 符号。 吸取了我们的教训 - 如果从生成恢复的 PR 的同一分支合并,请仔细 git diff 和审查提交! 我遇到了一个问题。我合并的分支没有任何新的提交。并且还原还原提交不会让我将开发分支合并到新功能分支并说“已经是最新的”。请帮忙。 @AstitvaSrivastava 你合并的分支没有新的提交,但你还需要合并吗?我对这些说法感到困惑。如果没有新的提交,那么就没有什么可以合并的了。但是,您所说的方式给了我一个可能的线索来解决您的问题。 “合并发展成为新功能”。您可能以错误的方式合并它们。如果 newfeature 是基于 develop 的,并且 develop 没有变化,那么 newfeature 并没有什么新的东西。尝试将新功能合并到开发中-如果您需要的话。我不能确定。【参考方案2】:

找到了一个 hacky 解决方案。但它有效。

eddiemoya 回答的任何内容都是完全有帮助的。非常感谢您的解释。我遇到了类似的情况。在哪里,我可以在 git diff <branch> 中看到很多内容,但 git merge 说已经是最新的了。

由于日志中有很多还原,我无法找到确切的还原提交。 (是的,坏事。一开始就不应该发生)

解决方案

git checkout branchX -- .

这会将所有从 branchX 的更改暂存到我当前的分支。 使用您最喜欢的 git 客户端,取消暂存和还原任何不打算使用的内容。

做一个新的提交并开心:)

【讨论】:

【参考方案3】:

我也遇到过同样的情况。我所做的是我刚刚创建了一个新分支,并从不同的提交中挑选了所有需要的文件,然后合并了这个分支。

动作如下所示:

创建了一个新分支 使用git cherry-pick -n xxxxxxx 从不同的提交中获取所需的文件 然后提交这些文件git commit -m 'Your commit message' 然后将这个樱桃采摘的分支合并到所需的分支中

【讨论】:

以上是关于为啥合并后GIT会说“已经是最新的”,但分支之间的差异仍然存在?的主要内容,如果未能解决你的问题,请参考以下文章

为啥“合并后删除分支”只删除远程GIT分支而不是本地?

Git,合并已经是最新的但有差异?

git:为啥我不能在壁球合并后删除我的分支?

Git:无法将功能分支合并到当前分支

Git:当我还没有提取更新时,为啥 git 会说“您的分支与 origin/main 是最新的”?

git分支合并为啥会发生冲突