Squashed提交到功能分支,并且现在无法将干净合并回主设备

时间:2016-05-02 15:12:34

标签: git squash git-squash

好的,所以我通过压缩一堆提交遇到了一些麻烦,想知道是否有办法从中恢复。发生了什么,

这是我们从哪里开始的:

  D (mybranch)
 /
A--B--C (master)

两个分支都完成了工作:

  D--E--F (mybranch)
 /
A--B--C--G--H (master)

合并了从mastermybranch的更改(不幸的是,此处被压扁,因此B,C,G和H合并为mybranch上的单个提交H':

  D--E--F--H' (mybranch)
 /         \   
A--B--C--G--H--L--M (master)

两个分支都完成了工作:

  D--E--F--H'--I--J--K (mybranch)
 /         \   
A--B--C--G--H--L--M--N--O (master)

现在我想将mybranch的更改合并回master,并且收到大量冲突,说明两者都修改了相同的文件。

有关我现在可以尝试从mybranchmaster进行全面合并的建议吗?

更新1

以下是git log

的输出
>git log --pretty=raw -n 1 d25ae411 (this is H')
commit d25ae411ffff9c59570437b50bfb89df7720af90
tree 3ffbb07a722fe70a66c64b257bb4a8c81235a027
parent aed6b526524db5c05bdb2518db18cf5ecfd8ef9d

>git log --pretty=raw -n 1 69c01f42 (this is H)
commit 69c01f42e73dad9f504c084de58b6a57f0d8506d
tree 323d506718f99d523fdd9529d8b6114a01657025
parent 7065134c416f7ecc6cf66c30ea5e019c625c9c19
parent 8170ca5ce1ce46df6b9f04d80cfad63b6f082b66

2 个答案:

答案 0 :(得分:1)

A"壁球合并"根本不是合并,所以这个绘图在几个重要方面是错误的:

  D--E--F--H'--I--J--K (mybranch)
 /         \
A--B--C--G--H--L--M--N--O (master)

...但幸运的是,它为我提供了我们需要知道的一切,知道如何尽可能轻松地处理这个问题。

首先,您说H'是从主 mybranch的压缩合并\可能应该是/(我们希望"稍后"提交到"更早和#34;提交的权利),但它实际上不应该表明合并,可能应该以不同的名称命名。

所以,以下是我将如何重新绘制图片片段(正如我可以管理的那样正确 - 你需要在使用它之前在你的端仔细地重新检查所有这些) :

  D--E--F----BCGH'--I--J--K   <-- mybranch
 /
A--B--C--G--H----L--M--N--O   <-- master

此处名为BCGH'的提交是提交B--C--G--H的壁球&#34;合并&#34; 1 ,您称之为H'。它是原始四次提交中所有工作的副本

使用rebase,省略壁球

您现在可能希望在mybranch的提示上重新定位master。这可能是最简单和最好的方法,但它确实意味着重写历史记录&#34; (假装你在提交O后开始工作)。为此,请使用交互式rebase:

$ git checkout mybranch
$ git rebase -i master

然后从BCGH'列表中专门删除提交pick。这将要求Git挑选每个提交DEFIJK(在其中)订单除非您还重新订购pick行:

  D--E--F----BCGH'--I--J--K   [will be abandoned]
 /
A--B--C--G--H----L--M--N--O   <-- master
                           \
                            D'-E'-F'-I'-J'-K'   <-- mybranch

使用merge,让Git完成工作

或者,如果你真的想要合并,那么从commit A开始创建一个 new (但是临时的)分支,你只需要选择那六个提交:< / p>

$ git checkout -b tempbranch mybranch~7  # this should start from A
$ git cherry-pick mybranch~7..mybranch~4 # pick D, E, and F
$ git cherry-pick mybranch~3..mybranch   # pick I, J, and K

  D--E--F----BCGH'--I--J--K   <-- mybranch
 /
A--B--C--G--H----L--M--N--O   <-- master
 \
  D'--E'--F'--I'--J'--K'      <-- tempbranch

请注意,tempbranch没有来自BCGH'的提交的master副本,否则与我们重新加入提示时的内容基本相同 of master。 2 制作此特定副本的目的是获取与此新提交K'关联的源树,因为现在我们可以运行:

$ git merge master

创建一个新的(尽管是临时的)合并提交T,不受BCGH'的干扰:

  D--E--F----BCGH'--I--J--K   <-- mybranch
 /
A--B--C--G--H----L--M--N--O   <-- master
 \                         \
  D'--E'--F'--I'--J'--K'----T   <-- tempbranch

如果我们将{em>真实T合并到{{},我们希望获得源树这个新的合并提交master 1}}。所以现在让我们开始合并,由于提交mybranch而导致合并冲突失败:

BCGH'

这会因冲突而失败,所以现在让我们通过丢弃整个合并结果并将其替换为临时合并$ git checkout mybranch $ git merge master 中的树来解决所有冲突。请注意,您必须位于git树的顶层,以便T引用所有内容:

.

第一步丢弃整个工作树(以及索引/登台区域内容),第二步从最$ git rm -rf . $ git checkout tempbranch -- . 提交创建一个全新的工作树(和索引内容),这是提交tempbranch

现在你可以提交结果了(虽然首先要仔细检查它,当然,你可以在分支T之前做到这一点,然后才能做到这一点)。一旦你提交,你将拥有:

tempbranch

其中 D--E--F----BCGH'--I--J--K-P <-- mybranch / / A--B--C--G--H----L--M--N--O <-- master \ \ D'--E'--F'--I'--J'--K'----T <-- tempbranch 是使用来自P的源树的正确合并。现在可以安全地完全删除T

tempbranch

并且你得到了Git使用省略提交$ git branch -D tempbranch 的临时分支所做的合并。

更多选项,以及关于如何以及为何做任何事情的说明

还有其他方法可以解决这个问题,例如从提交BCGH'开始创建新分支,从F进行真正的合并到这个新分支(而不是压缩&#34;合并& #34;),然后挑选masterI并从K进行另一次真正的合并。

与任何其他方法相比,使用任何一种方法的唯一理由是:

  • 如果您更喜欢这种方法;
  • 如果你更容易;和/或
  • 如果其他人有一些提交,而你又不想让其他人做更多工作。

最后,提交给你两件事: state (工作树,加上提交作者,日期和日志消息等元数据)和历史记录(在此提交之前提交了什么提交?)。我们的想法是根据需要提供尽可能多的提交,以提供足够的状态和历史记录,以实现合理的开发,同时不提供如此多的状态和历史来掩盖意义并禁止合作开发。

1 &#34; merge&#34;是因为,壁球合并不是合并。合并是两个或更多父母的提交,这些壁球&#34;合并&#34;提交不记录第二个父母:他们丢弃关键信息,这就是为什么如果你不小心他们就会变得那么麻烦。

2 我在这里的意思是提交与我们想要改装的时候一样。当然,它在关联的源树方面是不同的,因为它不包含masterBC中完成的任何工作。 ,GHLMN。从O开始的rebase从完成所有工作的源树开始。

答案 1 :(得分:0)

我怀疑历史记录不是您认为的那样,并且mastermybranch的变更合并在某种程度上没有做好。

最初的合并是否因许多冲突和修复而痛苦?如果没有,我会摆脱它并从头开始

git checkout -b mybranch_test F
git rebase --onto F H' mybranch_test

不等,您可以执行git checkout myrbanch; git rebase --interactive F并删除H'提交。

这应该很容易测试,并且使用git尝试这样的东西是免费的,所以试一试。

这一切都基于H'合并没有引入主要的冲突诱导变化的假设,这可能是也可能不是。