最近在Mercurial中维护发布分支时,最近有几个关于跳过更改的问题。例如:
自从它在2.0中引入以来,我一直想知道如何使用graft
来避免这个问题。给出这样的修订树:
A---B---C---D---E---F---G---H---I---J
假设我们需要创建一个跳过Evil更改E
的发布分支。
hg update -r D
hg graft "F::J"
给我们:
A---B---C---D---E---F---G---H---I---J
\
--F'--G'--H'--I'--J'
transplant
会从F::J
生成补丁,然后将它们应用到D
,但据说graft
使用3向合并而不是补丁。那么......这是怎么回事?为什么会更好?让我说我现在修复E
,并将其合并到我的发布分支中。
--E2-----------------
/ \
A---B---C---D---E---F---G---H---I---J---M1
\ \
--F'--G'--H'--I'--J'---------M2--
M1是直接合并;没什么特别的。 M2正在合并具有“相同”(或至少等同)变化的分支。
D
,J'
和M1
进行的正常三向合并吗?最后......
答案 0 :(得分:119)
当您更新到D
并移植F::J
时,Mercurial会运行多个合并。它将从这个合并开始:
M = three_way_merge(local=D, other=F, base=E)
如果我们为状态+d
和C
之间的差异写D
,那么我们从:
+d +e +f
---- C ---- D ---- E ---- F ----
顺时针旋转图形90度,上面的三向合并如下所示:
-e
.---- D
/
E
\
'---- F
+f
也就是说,我们假设我们从E
开始,并应用-e
的反面来转到D
。我认为是+e
的反向补丁。从E
开始,我们还使用正常的delta F
进入状态+f
。这里没什么奇怪的 - 我们已经在存储库中拥有所有状态(D
,E
和F
)。如此看来,很明显我们可以合并D
和F
。
合并是“完成钻石”的问题。因此,我们发现了一个新的状态M
,它是D
和F
的混合,其中D
与M
之间的差异类似于{{1} +f
与F
之间的差异与M
相似。它看起来像这样:
-e
-e +f'
.---- D ----.
/ \
E M
\ /
'---- F ----'
+f -e'
delta变为+f
,+f'
delta变为-e
。这只是一个正常的三向合并,但效果很有意思:我们已将-e'
应用于F
而不是D
!
合并后,E
到M
的第二个父级将被删除:
F
重申:我们已将 -e +f'
.---- D ----.
/ \
E M
\
'---- F
+f
的“效果”复制到F
,也就是说,我们找到了应用于D
的delta(+f'
)与D
应用+f
时的效果相同。我们可以稍微理清图表来获得:
E
结果是 +f'
--- D ---- M
\
'---- E ---- F
+e +f
使用完整的三向机制嫁接到F
。
Q1:这里发生了什么?那么......这是怎么回事?为什么会更好?
A1:使用合并比补丁更好,因为合并机器会考虑重命名等事项。
Q2:此合并是使用D,J'和M1进行的正常3向合并吗?
A2:是的,嫁接不会改变图表的拓扑结构。
问题3: mercurial存储/使用了有关移植操作的额外信息以帮助合并吗?
A3:否。
问题4:这样的流程有哪些潜在问题?
A4:从合并的角度来看,它应该可以正常工作。它会复制一些可能让人感到困惑的历史。
答案 1 :(得分:6)
Q1:有冲突时会有所帮助。您可以使用常用的合并工具(对我而言,它是内联冲突标记,我使用Emacs的smerge模式编辑)。
Q2:这是正常的合并。
问题3:否。
第四季:我认为拥有两个几乎相同的分支是很难的。