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

时间:2013-04-01 01:43:16

标签: git merge conflict

我最初在'newfeature'分支工作,我被召唤来紧急修复现场分支上的错误。我创建了一个名为'generalmaintenance'的分支,完成了工作,然后切换到开发并合并它。我现在想要返回'newfeature'分支并合并我之前合并到它的更改。

当我切换到'newfeature'并合并'develop'时,3个文件中存在冲突。

我纠结了解决冲突并最终决定在Aptana Studio 3(这是我的IDE)的'Team'菜单中使用“Revert”命令。我预计这会让我回到合并之前,它似乎已经完成了。

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

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

3 个答案:

答案 0 :(得分:54)

还原合并与重置合并

我的猜测是你实际 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 ne new sentence.

然后还原它,revert命令会创建一个刚刚执行相反diff的新提交,它只是翻转符号。

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

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

还原合并

但是,在非快速合并的情况下,它可能会产生不良影响。

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

假设W是一个reversion提交,你可以看到运行git log newfeature仍将包含来自develop分支的所有提交。因此,来自develop的其他合并将无效,因为它不会从您的分支中看到任何遗漏。

使用git reset代替还原。

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

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

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

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

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

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

解决方案 - 恢复还原。

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

让我们假设您在develop中尊重合并后,在newfeature分支上做了一些工作。你的历史看起来像这样。

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

如果您现在将develop合并到newfeature,则只会获得D,因为它是唯一尚未成为newfeature分支历史记录一部分的提交。您还需要做的是恢复W提交 - git revert W应该执行git merge develop之后的操作。

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

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

<强> TL; DR

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

develop

答案 1 :(得分:2)

找到了一个骇人听闻的解决方案。但这有效。

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

由于日志中有大量还原,因此我无法找到确切的还原提交。 (是的,不好的事情。首先不应该发生)

解决方案

git checkout branchX -- .

这会将所有更改从branchX转移到我当前的分支。 在您最喜欢的git客户端上使用,取消登台并还原所有不需要的内容。

重新提交并感到高兴:)

答案 2 :(得分:0)

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

动作如下:

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