226

举个例子:

我在主题分支中有一些工作,现在我准备合并回 master:

* eb3b733 3     [master] [origin/master]
| * b62cae6 2   [topic]
|/  
* 38abeae 1

我从 master 执行合并,解决冲突,现在我有:

*   8101fe3 Merge branch 'topic'  [master]
|\  
| * b62cae6 2                     [topic]
* | eb3b733 3                     [origin/master]
|/  
* 38abeae 1

现在,合并花了我一些时间,所以我再次获取并注意到远程主分支有新的变化:

*   8101fe3 Merge branch 'topic'  [master]
|\  
| * b62cae6 2                     [topic]
| | * e7affba 4                   [origin/master]
| |/  
|/|   
* | eb3b733 3
|/  
* 38abeae 1

如果我git rebase origin/master从 master 尝试,我将被迫再次解决所有冲突,并且我也会丢失合并提交:

* d4de423 2       [master]
* e7affba 4       [origin/master]
* eb3b733 3
| * b62cae6 2     [topic]
|/  
* 38abeae 1

有没有一种干净的方法来重新合并提交,所以我最终得到了如下所示的历史记录?

*   51984c7 Merge branch 'topic'  [master]
|\  
| * b62cae6 2                     [topic]
* | e7affba 4                     [origin/master]
* | eb3b733 3
|/  
* 38abeae 1
4

5 回答 5

166

这里有两个选项。

一种是进行交互式变基并编辑合并提交,手动重做合并并继续变基。

另一种是使用--rebase-mergeson 选项git rebase,手册中描述如下:

默认情况下,rebase 将简单地从 todo 列表中删除合并提交,并将 rebase 提交放入单个线性分支。使用 --rebase-merges,rebase 将尝试通过重新创建合并提交来保留要重新设置的提交中的分支结构。这些合并提交中的任何已解决的合并冲突或手动修改都必须手动解决/重新应用。"

于 2011-01-24T16:01:03.460 回答
42

好的,这是一个老问题,它已经有一个接受的答案@siride,但在我的情况下,这个答案还不够,因为它--preserve-merges迫使你第二次解决所有冲突。我的解决方案是基于这个想法,@Tobi B但使用精确的分步命令

我们将从原始问题中的相同状态开始:

*   8101fe3 Merge branch 'topic'  [HEAD -> master]
|\  
| * b62cae6 2                     [topic]
| |
| | * f5a7ca8 5                   [origin/master]
| | * e7affba 4
| |/  
|/|   
* | eb3b733 3
|/  
* 38abeae 1

请注意,我们在 master 之前有 2 次提交,因此挑选樱桃不起作用。

  1. 首先,让我们创建正确的历史记录:

     git checkout -b correct-history # create new branch to save master for future
     git rebase --strategy=ours --preserve-merges origin/master
    

    我们--preserve-merges用来将我们的合并提交保存在历史记录中。我们--strategy=ours习惯于忽略所有合并冲突,因为我们不关心合并提交中的内容,我们只需要一个好的历史记录。

    历史将如下所示(忽略主人):

     *   51984c7 Merge branch 'topic'  [HEAD -> correct-history]
     |\  
     | * b62cae6 2                     [topic]
     * | f5a7ca8 5                     [origin/master]
     * | e7affba 4
     * | eb3b733 3
     |/  
     * 38abeae 1
    
  2. 现在让我们得到正确的索引。

     git checkout master # return to our master branch
     git merge origin/master # merge origin/master on top of our master
    

    我们可能会在这里遇到一些额外的合并冲突,但这只会是文件在 和 之间更改的冲突8101fe3f5a7ca8它不包括已经解决的冲突topic

    历史看起来像这样(忽略正确的历史):

     *   94f1484 Merge branch 'origin/master'  [HEAD -> master]
     |\  
     * | f5a7ca8 5                   [origin/master]
     * | e7affba 4
     | *   8101fe3 Merge branch 'topic'
     | |\  
     | | * b62cae6 2                     [topic]
     |/ /
     * / eb3b733 3
     |/  
     * 38abeae 1
    
  3. 最后一个阶段是将我们的分支与正确的历史记录和具有正确索引的分支结合起来

     git reset --soft correct-history
     git commit --amend
    

    我们使用reset --soft将我们的分支(和历史)重置为正确的历史,但保留索引和工作树原样。然后,我们使用commit --amend来自 master 的良好索引重写我们的合并提交,它曾经有不正确的索引。

    最后我们将拥有这个状态(注意另一个顶部提交的 id):

     *   13e6d03 Merge branch 'topic'  [HEAD -> master]
     |\  
     | * b62cae6 2                     [topic]
     * | f5a7ca8 5                     [origin/master]
     * | e7affba 4
     * | eb3b733 3
     |/  
     * 38abeae 1
    
于 2017-12-14T17:13:54.490 回答
7

鉴于我刚刚浪费了一天的时间试图弄清楚这一点,并且在同事的帮助下实际上找到了解决方案,我想我应该插话。

我们有一个庞大的代码库,我们必须同时处理 2 个被大量修改的分支。如果你有一个主分支和一个辅助分支。

当我将辅助分支合并到主分支时,主分支中的工作仍在继续,当我完成时,我无法推送我的更改,因为它们不兼容。

因此,我需要“重新设置”我的“合并”。

这就是我们最终做到的方式:

1)记下SHA。例如:c4a924d458ea0629c0d694f1b9e9576a3ecf506b

git log -1

2)创建正确的历史,但这会破坏合并。

git rebase -s ours --preserve-merges origin/master

3)记下SHA。例如:29dd8101d78

git log -1

4)现在重置到你之前的位置

git reset c4a924d458ea0629c0d694f1b9e9576a3ecf506b --hard

5) 现在将当前的 master 合并到你的工作分支中

git merge origin/master
git mergetool
git commit -m"correct files

6) 既然您拥有正确的文件,但历史记录错误,请使用以下命令获取正确的历史记录:

git reset 29dd8101d78 --soft

7) 然后 --amend 原始合并提交中的结果

git commit --amend

瞧!

于 2017-12-14T16:47:31.880 回答
1

看起来您想要做的是删除您的第一个合并。您可以按照以下步骤操作:

git checkout master      # Let's make sure we are on master branch
git reset --hard master~ # Let's get back to master before the merge
git pull                 # or git merge remote/master
git merge topic

那会给你你想要的。

于 2011-01-24T18:10:57.640 回答
-2
  • 从您的合并提交
  • 樱桃采摘应该很容易的新变化
  • 复制你的东西
  • 只需从本地副本复制文件即可重做合并并解决冲突;)
于 2017-11-30T16:26:45.677 回答