重新基于Git合并提交

举个例子:

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

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

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

*   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

如果我从master尝试git rebase origin/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
151515 次浏览

这里有两种选择。

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

另一种方法是在git rebase上使用--rebase-merges选项,该选项的描述如下:

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

看起来你要做的是删除第一个合并。您可以执行以下步骤:

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

那会给你你想要的。

  • 从合并提交中
  • 挑选新的变化应该很容易
  • 复制你的东西
  • 重做合并和解决冲突,只需从您的本地副本复制文件;)

考虑到我刚刚花了一天时间试图解决这个问题,并在同事的帮助下找到了解决方案,我想我应该加入进来。

我们有一个很大的代码库,我们必须处理2个分支同时被大量修改。这里有一个主分支和一个副分支。

当我将次要分支合并到主分支中时,工作仍在主分支中继续,当我完成时,我不能推动我的更改,因为它们是不兼容的。

因此,我需要“重新调整”我的“合并”。

我们最终是这样做的:

1)记录SHA。例:c4a924d458ea0629c0d694f1b9e9576a3ecf506b

git log -1

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

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

3)做好SHA记录。例:29 dd8101d78

git log -1

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

git reset c4a924d458ea0629c0d694f1b9e9576a3ecf506b --hard

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

git merge origin/master
git mergetool
git commit -m"correct files
现在你有了正确的文件,但历史记录是错误的,那就找正确的

git reset 29dd8101d78 --soft

7)然后——修改原始合并提交的结果

git commit --amend

瞧!

好吧,这是一个老问题,它已经有了一个被@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来忽略所有合并冲突,因为我们不关心合并提交中会有什么内容,我们只需要一个漂亮的历史记录

    历史记录是这样的(忽略master):

     *   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将分支(和历史记录)重置为correct-history,但索引和工作树保持原样。然后,我们使用commit --amend重写合并提交,它以前有不正确的索引,使用来自master的良好索引。

    最后我们会得到这样的状态(注意top commit的另一个id):

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