变基 Git 合并提交
以以下情况为例:
我在主题分支中有一些工作,现在我准备合并回主分支:
* eb3b733 3 [master] [origin/master]
| * b62cae6 2 [topic]
|/
* 38abeae 1
我从主分支执行合并,解决冲突,现在我有:
* 8101fe3 Merge branch 'topic' [master]
|\
| * b62cae6 2 [topic]
* | eb3b733 3 [origin/master]
|/
* 38abeae 1
现在,合并花了我一些时间,所以我再次执行 fetch 并注意到远程 master 分支有新的更改:
* 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
Take the following case:
I have some work in a topic branch and now I'm ready to merge back to master:
* eb3b733 3 [master] [origin/master]
| * b62cae6 2 [topic]
|/
* 38abeae 1
I perform the merge from master, resolve the conflicts and now I have:
* 8101fe3 Merge branch 'topic' [master]
|\
| * b62cae6 2 [topic]
* | eb3b733 3 [origin/master]
|/
* 38abeae 1
Now, the merge took me some time, so I do another fetch and notice that the remote master branch has new changes:
* 8101fe3 Merge branch 'topic' [master]
|\
| * b62cae6 2 [topic]
| | * e7affba 4 [origin/master]
| |/
|/|
* | eb3b733 3
|/
* 38abeae 1
If I try git rebase origin/master
from master, I'm forced to resolve all conflicts again, and I also lose the merge commit:
* d4de423 2 [master]
* e7affba 4 [origin/master]
* eb3b733 3
| * b62cae6 2 [topic]
|/
* 38abeae 1
Is there a clean way to rebase the merge commit so I end up with a history like the one I show below?
* 51984c7 Merge branch 'topic' [master]
|\
| * b62cae6 2 [topic]
* | e7affba 4 [origin/master]
* | eb3b733 3
|/
* 38abeae 1
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
这里有两个选择。
一种是进行交互式变基并编辑合并提交,手动重做合并并继续变基。
另一种是使用
git rebase
上的--rebase-merges
选项,手册中的描述如下:There are two options here.
One is to do an interactive rebase and edit the merge commit, redo the merge manually and continue the rebase.
Another is to use the
--rebase-merges
option ongit rebase
, which is described as follows from the manual:好吧,这是一个老问题,并且
@siride
已经接受了答案,但是在我的例子中,答案还不够,因为--preserve-merges
迫使您再次解决所有冲突。我的解决方案基于@Tobi B
的想法,但具有精确的分步步骤命令我们将从原始问题中发现的相同状态开始:
请注意,我们在 master 之前有 2 个提交,因此樱桃采摘不起作用。
首先,让我们创建正确的历史记录:
我们使用
--preserve-merges
将合并提交保存在历史记录中。我们使用
--strategy=ours
来忽略所有合并冲突,因为我们不关心合并提交中的内容,我们只需要一个很好的历史记录。历史记录将如下所示(忽略master):
现在让我们获取正确的索引。
我们可能会在这里遇到一些额外的合并冲突,但这只是来自
8101fe3
和f5a7ca8
之间更改的文件的冲突,它不包括来自8101fe3
和f5a7ca8
之间已解决的冲突代码>主题历史记录将如下所示(忽略正确的历史记录):
最后一个阶段是将我们的分支与正确的历史记录和分支与正确的索引结合起来
我们使用
reset --soft
将我们的分支(和历史记录)重置为正确的历史记录,但保留索引和工作树不变。然后我们使用commit --amend
来重写我们的合并提交,它曾经有不正确的索引,而来自 master 的良好索引。最终我们将得到这个状态(注意顶部提交的另一个 id):
Ok, it's an old question and it already has an accepted answer by
@siride
, but that answer wasn't enough in my case, as--preserve-merges
forces you to resolve all conflicts a second time. My solution is based on the idea by@Tobi B
but with exact step-by-step commandsWe'll start in the same state found in the original question:
Note that we have 2 commits ahead of master, so cherry-picking won't work.
First of all, let's create the correct history:
We use
--preserve-merges
to save our merge commit in history.We use
--strategy=ours
to ignore all merge conflicts as we don't care about what contents will be in that merged commit, we only need a nice history.The history will look like this (ignoring master):
Let's get the correct index now.
We may get some additional merge conflicts here, but that would only be conflicts from files changed between
8101fe3
andf5a7ca8
, it doesn't include already resolved conflicts fromtopic
History will looks like this (ignoring correct-history):
The last stage is to combine our branch with correct history and branch with correct index
We use
reset --soft
to reset our branch (and history) to correct-history, but leave index and working tree as is. Then we usecommit --amend
to rewrite our merge commit, that used to have the incorrect index, with our good index from master.In the end we will have this state (note another id of top commit):
鉴于我刚刚花了一天时间试图解决这个问题,并且在同事的帮助下实际上找到了解决方案,我想我应该插话一下。
我们有一个很大的代码库,我们必须处理 2 个被大量修改的分支同一时间。如果有的话,有一个主分支和一个次分支。
当我将辅助分支合并到主分支时,主分支中的工作仍在继续,当我完成时,我无法推送我的更改,因为它们不兼容。
因此,我需要“重新调整”我的“合并”。
这就是我们最终做到的:
1) 记下 SHA。例如:c4a924d458ea0629c0d694f1b9e9576a3ecf506b
2) 创建正确的历史记录,但这会破坏合并。
3) 记下 SHA。例如:29dd8101d78
4) 现在重置到之前的位置
5) 现在将当前的 master 合并到你的工作分支
6) 现在你有了正确的文件,但历史记录错误,获取正确的文件
在您的更改之上添加历史记录:
7) 然后 --修改原始合并提交中的结果
瞧!
Given that I just lost a day trying to figure this out and actually found a solution with the help of a coworker, I thought I should chime in.
We have a large code base and we have to deal with 2 branch heavily being modified at the same time. There is a main branch and a secondary branch if you which.
While I merge the secondary branch into the main branch, work continues in the main branch and by the time i'm done, I can't push my changes because they are incompatible.
I therefore need to "rebase" my "merge".
This is how we finally did it :
1) make note of the SHA. ex.: c4a924d458ea0629c0d694f1b9e9576a3ecf506b
2) Create the proper history but this will break the merge.
3) make note of the SHA. ex.: 29dd8101d78
4) Now reset to where you were before
5) Now merge the current master into your working branch
6) Now that you have the right files, but the wrong history, get the right
history on top of your change with :
7) And then --amend the results in your original merge commit
Voila!
看起来您想要做的是删除第一个合并。您可以按照以下步骤操作:
这会给您您想要的。
It looks like what you want to do is remove your first merge. You could follow the following procedure:
That would give you what you want.