38

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

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

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

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

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

4

3 回答 3

71

恢复合并与重置合并

我的猜测是你实际上 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 是一个回复提交,你可以看到 runninggit log newfeature仍然会包含来自开发分支的所有提交。结果,来自的其他合并develop将不起作用,因为它看不到您的分支中缺少任何内容。

使用git reset而不是还原。

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

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

正如您所看到的,这种技术不会像某些人认为的那样消除提交,它只是将您的分支移回您选择的提交。现在如果你跑了git log newfeature,你只会得到 commit 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

如果你合并developnewfeature现在,你只会得到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建议在合并最近的更改之前develop还原还原,我怀疑这样做以该顺序触发冲突的可能性较低。

TL;博士

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

git revert <commit>

于 2013-04-01T04:33:04.843 回答
8

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

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

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

解决方案

git checkout branchX -- .

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

做出新的承诺并快乐:)

于 2018-11-02T08:17:10.040 回答
2

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

操作如下所示:

  • 创建了一个新分支
  • 用于git cherry-pick -n xxxxxxx从不同的提交中获取所需的文件
  • 然后提交这些文件git commit -m 'Your commit message'
  • 然后将这个樱桃采摘的分支合并到所需的分支中
于 2020-10-15T15:01:28.223 回答