Jak*_*ake 5 git rebase meld git-rebase
假设我做了一个交互式变基git rebase -i
.如果出现一些冲突,我可能会遇到合并冲突并要求进行3向合并.使用时meld
,我会看到三个窗口:( LOCAL
左),???
(中)和REMOTE
(右).在这里,???
我的意思是,meld
它没有提供一些特殊的名称来附加到文件.
在正常合并期间,这是有道理的,因为中间是共同的祖先,并且您正在将本地和远程更改合并到该祖先.然而,在交互式rebase期间似乎并非如此 - 目前还不清楚每个文件代表什么.
在交互式rebase期间,3向合并中的这些文件各自代表什么?编辑这些文件时,我的目标是什么?
更新:根据我看到的评论和实验:
LOCAL
):此时在提交重播序列中的文件的本地版本.REMOTE
):刚刚应用当前提交之后的文件状态.因此,我的任务是从中间到右边确定增量,然后将此增量应用于左侧.在新的提交序列中应用当前提交增量后,Middle应反映文件的状态.
请注意,此配置似乎特定于融合,至少在某种程度上.对于其他编辑者,Git的3向合并行为可能有所不同.
中间版本是合并基础,就像一个git merge
.
(名称"other"可能比"remote"更合适,因为不要求合并的另一侧是远程,并且由于Mercurial始终使用名称"other",因此Git不需要匹配Mercurial但是一些一致性可能很好.请注意,Git在这里也使用"我们的"和"他们的"名称,所以我们永远不会从Git获得100%的一致性:-))
有总是合并基地.
通常我们甚至不必找到它,因为当作为补丁处理时,每个补丁都应用得很干净(不尝试三向合并).但有时补丁不会干净的应用,我们也不得不回落到三路合并.
(顺便说一句,您可以禁用此回退.请参阅--3way
,--no-3way
以及am.threeWay
在git-am文档中,尽管此处链接的页面已经过时,因为这些控件最近已更改.)
$ git rebase -i
pick aaaaaaa first commit
pick bbbbbbb second commit
pick ccccccc third commit
Run Code Online (Sandbox Code Playgroud)
让我们绘制提交图,这样我们就可以看到我们正在改变的内容:
A - B - C <-- branch
/
... - o - *
\
G - H <-- origin/branch
Run Code Online (Sandbox Code Playgroud)
我们将挑选提交A
,B
和C
(A
= aaaaaaa
等),以便我们得到这个结果,最后:
A - B - C [abandoned]
/
... - o - * A' - B' - C' <-- branch
\ /
G - H <-- origin/branch
Run Code Online (Sandbox Code Playgroud)
让我们仔细看看第一个樱桃选择A
.
这会将(diff)A
与其父级(即commit )进行比较*
,并尝试将生成的diff应用于提交H
.
H
然而,承诺在提交方面有所偏离*
.事实上,我们可以找到A
和之间的合并基础H
,它是......提交*
.这实际上是一个相当不错的合并基础,尽管如果Git可以按原样应用补丁最好,而不必回退到三向合并代码.
因此,承诺*
是,当樱桃采摘合并基础A
上H
.合并完成后,我们得到新的提交A'
.(例如,它可能是新的SHA-1 ID aaaaaa1
.可能不是;我们只需要调用它A'
.)
现在我们将挑选B
.这B
与它的父亲相差甚远A
,并尝试将差异应用于A'
.
A'
然而,承诺在提交方面有所偏离B
.事实上,我们可以在B
和之间找到合并基础A'
,这就是...... *
再次提交.不幸的是,这是一个可怜的合并基地.幸运的是,如果补丁不能按原样应用,Git只会依赖它,通常它可以.但如果不能,Git会对 编辑 Git作弊.(此代码最近在版本2.6中已更改,但总体策略保持不变.)*
vs B
和*
vs进行差异化A'
并尝试合并这两个差异.请注意,*
vs B
包含了我们所做的所有更改A
,但*
vs A'
也包含了所有相同的A
更改,因此如果我们幸运的话,Git会注意到已经合并的更改并且不会复制它们.
考虑git diff
用于显示从提交A
到提交的更改的实际输出B
.这包括index
一行:
diff --git a/foo b/foo
index f0b98f8..0ea3286 100644
Run Code Online (Sandbox Code Playgroud)
左边的值是foo
commit 中文件版本的(缩写)哈希值A
.右侧的值是commit中文件版本的哈希值B
.
Git只是从左侧哈希中伪造了一个合并库.换句话说,提交中的文件版本A
变为伪造的合并库.(Git传递--build-fake-ancestor
给git apply
.这需要特定文件blob对象在存储库中,但它们是因为它们处于提交状态A
.对于通过电子邮件发送的补丁,Git使用相同的代码,但blob可能存在也可能不存在.)
请注意,Git实际上A
也是在提取樱桃时执行此操作,但这次合并基础文件是来自commit的版本*
,它实际上是合并基础.
最后,我们挑选C
.这DIFFS B
VS C
,就像我们显示差异A
VS B
最后一次.如果我们可以按原样应用补丁,那么好; 如果没有,我们再次使用commit 与以前一样,假装版本*
作为合并基础.这又是一个非常糟糕的合并基地.B
是公共基础.
顺便提一下,这也解释了为什么你倾向于为这些rebase反复看到相同的合并冲突:我们每次使用相同的合并库.(启用git rerere
可以提供帮助.)
归档时间: |
|
查看次数: |
1980 次 |
最近记录: |