变基 Git 合并提交

发布于 2024-10-13 21:41:21 字数 1093 浏览 10 评论 0原文

以以下情况为例:

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

* 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

放肆 2024-10-20 21:41:21

这里有两个选择。

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

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

默认情况下,变基只会从待办事项列表中删除合并提交,并将变基提交放入单个线性分支中。使用 --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 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."

此刻的回忆 2024-10-20 21:41:21

好吧,这是一个老问题,并且 @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 # 创建新分支以保存 master 供将来使用
     git rebase --strategy=ours --preserve-merges origin/master
    

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

    历史记录将如下所示(忽略master):

     * 51984c7 合并分支 'topic' [HEAD ->正确的历史]
     |\  
     | * b62cae6 2 [主题]
     * | f5a7ca8 5 [起源/主]
     * | e7affba 4
     * | eb3b733 3
     |/  
     * 38abeae 1
    
  2. 现在让我们获取正确的索引。

     git checkout master # 返回到我们的 master 分支
     git merge origin/master # 将 origin/master 合并到我们的 master 之上
    

    我们可能会在这里遇到一些额外的合并冲突,但这只是来自 8101fe3f5a7ca8 之间更改的文件的冲突,它不包括来自 8101fe3f5a7ca8 之间已解决的冲突代码>主题

    历史记录将如下所示(忽略正确的历史记录):

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

     git reset --soft Correct-history
     git commit --修改
    

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

    最终我们将得到这个状态(注意顶部提交的另一个 id):

     * 13e6d03 合并分支 'topic' [HEAD ->掌握]
     |\  
     | * b62cae6 2 [主题]
     * | f5a7ca8 5 [起源/主]
     * | e7affba 4
     * | eb3b733 3
     |/  
     * 38abeae 1
    

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 commands

We'll start in the same state found in the original 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 of master, so cherry-picking won't work.

  1. First of all, let's create the correct history:

     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 merged commit, we only need a nice history.

    The history will look like this (ignoring master):

     *   51984c7 Merge branch 'topic'  [HEAD -> correct-history]
     |\  
     | * b62cae6 2                     [topic]
     * | f5a7ca8 5                     [origin/master]
     * | e7affba 4
     * | eb3b733 3
     |/  
     * 38abeae 1
    
  2. Let's get the 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 would only be conflicts from files changed between 8101fe3 and f5a7ca8, it doesn't include already resolved conflicts from topic

    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
    
  3. 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 use commit --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):

     *   13e6d03 Merge branch 'topic'  [HEAD -> master]
     |\  
     | * b62cae6 2                     [topic]
     * | f5a7ca8 5                     [origin/master]
     * | e7affba 4
     * | eb3b733 3
     |/  
     * 38abeae 1
    
裂开嘴轻声笑有多痛 2024-10-20 21:41:21

鉴于我刚刚花了一天时间试图解决这个问题,并且在同事的帮助下实际上找到了解决方案,我想我应该插话一下。

我们有一个很大的代码库,我们必须处理 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) 然后 --修改原始合并提交中的结果

git commit --amend

瞧!

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

git log -1

2) Create the proper history but this will break the merge.

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

3) make note of the SHA. ex.: 29dd8101d78

git log -1

4) Now reset to where you were before

git reset c4a924d458ea0629c0d694f1b9e9576a3ecf506b --hard

5) Now merge the current master into your working branch

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 :

git reset 29dd8101d78 --soft

7) And then --amend the results in your original merge commit

git commit --amend

Voila!

蓝天 2024-10-20 21:41:21

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

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

这会给您您想要的。

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.

十级心震 2024-10-20 21:41:21
  • 从您的合并提交中
  • 挑选新的更改,这应该很容易
  • 复制您的内容
  • 重做合并并通过仅从本地副本复制文件来解决冲突;)
  • 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 ;)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文