重新设置 Git 合并提交
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4783599/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Rebasing a Git merge commit
提问by jipumarino
Take the following case:
看下面的案例:
I have some work in a topic branch and now I'm ready to merge back to master:
我在一个主题分支中有一些工作,现在我准备合并回 master:
* eb3b733 3 [master] [origin/master]
| * b62cae6 2 [topic]
|/
* 38abeae 1
I perform the merge from master, resolve the conflicts and now I have:
我从 master 执行合并,解决冲突,现在我有:
* 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:
现在,合并花了我一些时间,所以我又做了一次 fetch 并注意到远程 master 分支有新的变化:
* 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:
如果我尝试从 master 执行 'git rebase origin/master',我将被迫再次解决所有冲突,并且我也会丢失合并提交:
* 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
采纳答案by siride
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 on git rebase
, which is described as follows from the manual: "By default, a rebase will simply drop merge commits from the todo list, and put the rebased commits into a single, linear branch. With --rebase-merges, the rebase will instead try to preserve the branching structure within the commits that are to be rebased, by recreating the merge commits. Any resolved merge conflicts or manual amendments in these merge commits will have to be resolved/re-applied manually."
另一种方法是使用--rebase-merges
on 选项git rebase
,手册中对它的描述如下:“默认情况下,rebase 将简单地从待办事项列表中删除合并提交,并将重新提交的提交放入单个线性分支中。使用 --rebase-合并时,rebase 将尝试通过重新创建合并提交来尝试保留要重新创建的提交中的分支结构。这些合并提交中任何已解决的合并冲突或手动修改都必须手动解决/重新应用。”
回答by Ivan Naydonov
Ok, that's an old question and it already have accepted answer by @siride
, but that answer wasn't enough in my case, as --preserve-merges
forces you to resolve all conflicts second time. My solution based on the idea by @Tobi B
but with exact step-by-step commands
好的,这是一个老问题,它已经接受了 的答案@siride
,但在我的情况下,该答案还不够,因为会--preserve-merges
迫使您第二次解决所有冲突。我的解决方案基于这个想法,@Tobi B
但具有精确的分步命令
So we'll start on such state based on example in the question:
因此,我们将根据问题中的示例开始这种状态:
* 8101fe3 Merge branch 'topic' [HEAD -> master]
|\
| * b62cae6 2 [topic]
| |
| | * f5a7ca8 5 [origin/master]
| | * e7affba 4
| |/
|/|
* | eb3b733 3
|/
* 38abeae 1
Note that we have 2 commits ahead master, so cherry-pick wouldn't work.
请注意,我们在 master 之前有 2 个提交,因此cherry-pick 不起作用。
First of all, let's create correct history that we want:
git checkout -b correct-history # create new branch to save master for future git rebase --strategy=ours --preserve-merges origin/master
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 merge commit, we only need nice history now.History will looks like that (ignoring master):
* 51984c7 Merge branch 'topic' [HEAD -> correct-history] |\ | * b62cae6 2 [topic] * | f5a7ca8 5 [origin/master] * | e7affba 4 * | eb3b733 3 |/ * 38abeae 1
Let's get correct index now.
git checkout master # return to our master branch git merge origin/master # merge origin/master on top of our master
We may get some additional merge conflicts here, but that's would only be conflicts from files changed between
8101fe3
andf5a7ca8
, but not includes already resolved conflicts fromtopic
History will looks like this (ignoring correct-history):
* 94f1484 Merge branch 'origin/master' [HEAD -> master] |\ * | f5a7ca8 5 [origin/master] * | e7affba 4 | * 8101fe3 Merge branch 'topic' | |\ | | * b62cae6 2 [topic] |/ / * / eb3b733 3 |/ * 38abeae 1
The last stage is to combine our branch with correct history and branch with correct index
git reset --soft correct-history git commit --amend
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 incorrect index, with our good index from master.In the end we will have such state (note another id of top commit):
* 13e6d03 Merge branch 'topic' [HEAD -> master] |\ | * b62cae6 2 [topic] * | f5a7ca8 5 [origin/master] * | e7affba 4 * | eb3b733 3 |/ * 38abeae 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
现在让我们得到正确的索引。
git checkout master # return to our master branch git merge origin/master # merge origin/master on top of our master
我们可能会在这里遇到一些额外的合并冲突,但这只会是来自
8101fe3
和之间更改的文件的冲突f5a7ca8
,但不包括已经解决的冲突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
最后一个阶段是将我们的分支与正确的历史和分支与正确的索引结合起来
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
回答by Claude Peloquin
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.
我们有一个庞大的代码库,我们必须同时处理 2 个被大量修改的分支。如果您选择哪个,则有一个主分支和一个辅助分支。
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
1) 记下 SHA。例如:c4a924d458ea0629c0d694f1b9e9576a3ecf506b
git log -1
2) Create the proper history but this will break the merge.
2)创建正确的历史记录,但这会破坏合并。
git rebase -s ours --preserve-merges origin/master
3) make note of the SHA. ex.: 29dd8101d78
3) 记下 SHA。例如:29dd8101d78
git log -1
4) Now reset to where you were before
4)现在重置到你以前的位置
git reset c4a924d458ea0629c0d694f1b9e9576a3ecf506b --hard
5) Now merge the current master into your working branch
5) 现在将当前的 master 合并到你的工作分支中
git merge origin/master
git mergetool
git commit -m"correct files
6) Now that you have the right files, but the wrong history, get the right history on top of your change with :
6) 现在您拥有正确的文件,但错误的历史记录,在您的更改之上获取正确的历史记录:
git reset 29dd8101d78 --soft
7) And then --amend the results in your original merge commit
7) 然后 --amend 原始合并提交中的结果
git commit --amend
Voila!
瞧!
回答by Antoine Pelisse
It looks like what you want to do is remove your first merge. You could follow the following procedure:
看起来您想要做的是删除您的第一个合并。您可以按照以下步骤操作:
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
That would give you what you want.
那会给你你想要的。
回答by Tobi B
- From your merge commit
- Cherry-pick the new change which should be easy
- copy your stuff
- redo the merge and resolve the conflicts by just copying the files from your local copy ;)
- 从你的合并提交
- Cherry-pick 应该很容易的新变化
- 复制你的东西
- 只需从本地副本中复制文件即可重做合并并解决冲突;)