好的,所以我通过压缩一堆提交遇到了一些麻烦,想知道是否有办法从中恢复。发生了什么,
这是我们从哪里开始的:
D (mybranch)
/
A--B--C (master)
两个分支都完成了工作:
D--E--F (mybranch)
/
A--B--C--G--H (master)
合并了从master
到mybranch
的更改(不幸的是,此处被压扁,因此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
,并且收到大量冲突,说明两者都修改了相同的文件。
有关我现在可以尝试从mybranch
到master
进行全面合并的建议吗?
更新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
答案 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'
。它是原始四次提交中所有工作的副本。
您现在可能希望在mybranch
的提示上重新定位master
。这可能是最简单和最好的方法,但它确实意味着重写历史记录&#34; (假装你在提交O
后开始工作)。为此,请使用交互式rebase:
$ git checkout mybranch
$ git rebase -i master
然后从BCGH'
列表中专门删除提交pick
。这将要求Git挑选每个提交D
,E
,F
,I
,J
和K
(在其中)订单除非您还重新订购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
或者,如果你真的想要合并,那么从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;),然后挑选master
到I
并从K
进行另一次真正的合并。
与任何其他方法相比,使用任何一种方法的唯一理由是:
最后,提交给你两件事: state (工作树,加上提交作者,日期和日志消息等元数据)和历史记录(在此提交之前提交了什么提交?)。我们的想法是根据需要提供尽可能多的提交,以提供足够的状态和历史记录,以实现合理的开发,同时不提供如此多的状态和历史来掩盖意义并禁止合作开发。
1 &#34; merge&#34;是因为,壁球合并不是合并。合并是两个或更多父母的提交,这些壁球&#34;合并&#34;提交不记录第二个父母:他们丢弃关键信息,这就是为什么如果你不小心他们就会变得那么麻烦。
2 我在这里的意思是提交与我们想要改装的时候一样。当然,它在关联的源树方面是不同的,因为它不包含master
,B
,C
中完成的任何工作。 ,G
,H
,L
,M
或N
。从O
开始的rebase从完成所有工作的源树开始。
答案 1 :(得分:0)
我怀疑历史记录不是您认为的那样,并且master
到mybranch
的变更合并在某种程度上没有做好。
最初的合并是否因许多冲突和修复而痛苦?如果没有,我会摆脱它并从头开始
git checkout -b mybranch_test F
git rebase --onto F H' mybranch_test
不等,您可以执行git checkout myrbanch; git rebase --interactive F
并删除H'
提交。
这应该很容易测试,并且使用git尝试这样的东西是免费的,所以试一试。
这一切都基于H'
合并没有引入主要的冲突诱导变化的假设,这可能是也可能不是。