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

Pet*_*now 29 git merge conflict

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

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

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

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

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

edd*_*oya 57

还原合并与重置合并

我的猜测是,你实际上 Already-up-to-date.

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

合并

     develop
        |
A---B---C
 \       \
  E---F---M
          |
      newfeature
Run Code Online (Sandbox Code Playgroud)

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

回复

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

-This is the old sentence.
+This is ne new sentence.
Run Code Online (Sandbox Code Playgroud)

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

-This is ne new sentence.
+This is the old sentence.
Run Code Online (Sandbox Code Playgroud)

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

恢复合并

但是,在非快速合并的情况下,它可能具有不期望的效果.

     develop
        |
A---B---C
 \       \
  E---F---M---W
              |
         newfeature
Run Code Online (Sandbox Code Playgroud)

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

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

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

     develop
        |
A---B---C
 \       \
  E---F---M
      |
  newfeature
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,这种技术并没有像某些人所想的那样消除提交,它只是将您的分支移回您选择的提交.现在,如果你跑了git log newfeature,你只会得到承诺F,EA.现在合并实际上已从您的分支历史记录中消失,因此稍后尝试重新合并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
Run Code Online (Sandbox Code Playgroud)

如果合并developnewfeature现在,你只会得到D,因为它的唯一的承诺,是不是已经是历史的一部分newfeature分支.你还需要做的是恢复W提交 - git revert W应该遵循的技巧git merge develop.

                 develop
                    |
A---B---C-----------D
 \       \           \
  E---F---M---W---M---G
                      |
                 newfeature
Run Code Online (Sandbox Code Playgroud)

这将恢复原始合并提交所做的所有更改 - 这些更改实际上是由C并且B已被还原W,然后D通过新的合并提交引入,我G建议合并最近的更改之前恢复还原develop,我怀疑这样做按此顺序触发冲突的可能性较小.

TL; DR

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

git revert <commit>

  • 仅供参考:我做了一些小的但重要的编辑来纠正一些事情.最重要的是,我在恢复合并提交时更正了我的示例.这是'git revert M`,我把它修正为`git revert W`.而且,第二个差异是错误的.解释恢复提交的那个.修正了+/-符号. (2认同)

Kat*_*tti 7

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

无论eddiemoya回答了什么,都非常有帮助。非常感谢您的解释。我遇到了类似的情况。在哪里,我能够看到很多内容,git diff <branch>但 git merge 说已经是最新的。

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

解决方案

git checkout branchX -- .
Run Code Online (Sandbox Code Playgroud)

这会将所有更改从 branchX 转移到我当前的分支。使用您最喜欢的 git 客户端,取消暂存并还原任何不想要的东西。

进行新的提交并感到高兴:)