`git rebase master` 如何将重新应用的提交检查为冲突?
How does `git rebase master` check a reapplying commit as a conflict?
假设我们有两个示例及其提交(line 1, line 2...
是 foo
文件的内容,它是工作目录中唯一的文件):
示例 1:
line 1 line 1
line 2 line 22
line 3 line 3
C0---------C1 [master]
\
C2 [test]
line 1
line 222
line 3
示例 2:
line 1 line 1
line 2 line 22
line 3 line 3
C0---------C1 [master]
\
C2--------C3 [test]
line 1 line 1
line 22 line 222
line 3 line 3
我 运行 git checkout test
和 git rebase master
在每个例子上,我看到例子 1 有冲突,而例子 2 没有冲突。
在示例 1 中,当重新应用 C2
时,我猜想 Git 在 C2
、C1
和 C0
上进行了 3 向合并,这检测到 C2
上的 "line 222"
与 C1
上的 "line 22"
不同,并且与基础 (C0
) 上的 "line 2"
不同,因此 Git检查是否存在冲突。
在示例2中,C2
的补丁已经在master
中,所以Git跳过它。但是当重新应用 C3
时,如果 Git 在 C3
、C1
和 C0
上进行了 3 向合并,它检测到 "line 222"
在 C3
与 C1
上的 "line 22"
不同,与基础 (C0
) 上的 "line 2"
不同,那么 Git 应该将其检查为冲突,但在真正的 Git 没有。
所以实际上,Git 变基如何将重新应用的提交检查为冲突?
每个提交都被(或好像被)git cherry-pick
复制。 cherry-pick 是一种合并,其合并基础是被选择的提交的父级,--ours
版本是 HEAD
提交,--theirs
版本是被选择的提交。所以,给定:
C0--C1 <-- master
\
C2--C3 <-- test
和:
git checkout test && git rebase master
Git会先把C2
复制到C2'
,再把C3
复制到C3'
.
复制C2
时,合并基数为C0
(C2
的parent),--ours
为C1
([=26=的tip) ]),而 --theirs
是 C2
(被复制)。复制完成后我们有这个:
C2' <-- HEAD
/
C0--C1 <-- master
\
C2--C3 <-- test
接下来,Git 挑选 C3
。因此,合并基础是 C2
(C3
的父级),--ours
是 C2'
,--theirs
是 C3
。
如果 base 与我们的差异 (git diff
) 与 base 与他们的差异触及同一文件的 "the same lines",则存在合并冲突。 "Same" 在这种情况下包括触摸行之后的一行。因此,将 C2
(基础)的内容与 C2'
和 C3
中的每一个进行比较,以查看我们更改了哪些行(C2
与 C2'
)和他们的(C2
对比 C3
)。如果我们在生成 C2'
时将 "their" 更改为第 2 行,则从 C2
到 C2'
的差异为空,因此通过获取文件可以轻松解决合并来自 C3
.
假设我们有两个示例及其提交(line 1, line 2...
是 foo
文件的内容,它是工作目录中唯一的文件):
示例 1:
line 1 line 1
line 2 line 22
line 3 line 3
C0---------C1 [master]
\
C2 [test]
line 1
line 222
line 3
示例 2:
line 1 line 1
line 2 line 22
line 3 line 3
C0---------C1 [master]
\
C2--------C3 [test]
line 1 line 1
line 22 line 222
line 3 line 3
我 运行 git checkout test
和 git rebase master
在每个例子上,我看到例子 1 有冲突,而例子 2 没有冲突。
在示例 1 中,当重新应用 C2
时,我猜想 Git 在 C2
、C1
和 C0
上进行了 3 向合并,这检测到 C2
上的 "line 222"
与 C1
上的 "line 22"
不同,并且与基础 (C0
) 上的 "line 2"
不同,因此 Git检查是否存在冲突。
在示例2中,C2
的补丁已经在master
中,所以Git跳过它。但是当重新应用 C3
时,如果 Git 在 C3
、C1
和 C0
上进行了 3 向合并,它检测到 "line 222"
在 C3
与 C1
上的 "line 22"
不同,与基础 (C0
) 上的 "line 2"
不同,那么 Git 应该将其检查为冲突,但在真正的 Git 没有。
所以实际上,Git 变基如何将重新应用的提交检查为冲突?
每个提交都被(或好像被)git cherry-pick
复制。 cherry-pick 是一种合并,其合并基础是被选择的提交的父级,--ours
版本是 HEAD
提交,--theirs
版本是被选择的提交。所以,给定:
C0--C1 <-- master
\
C2--C3 <-- test
和:
git checkout test && git rebase master
Git会先把C2
复制到C2'
,再把C3
复制到C3'
.
复制C2
时,合并基数为C0
(C2
的parent),--ours
为C1
([=26=的tip) ]),而 --theirs
是 C2
(被复制)。复制完成后我们有这个:
C2' <-- HEAD
/
C0--C1 <-- master
\
C2--C3 <-- test
接下来,Git 挑选 C3
。因此,合并基础是 C2
(C3
的父级),--ours
是 C2'
,--theirs
是 C3
。
如果 base 与我们的差异 (git diff
) 与 base 与他们的差异触及同一文件的 "the same lines",则存在合并冲突。 "Same" 在这种情况下包括触摸行之后的一行。因此,将 C2
(基础)的内容与 C2'
和 C3
中的每一个进行比较,以查看我们更改了哪些行(C2
与 C2'
)和他们的(C2
对比 C3
)。如果我们在生成 C2'
时将 "their" 更改为第 2 行,则从 C2
到 C2'
的差异为空,因此通过获取文件可以轻松解决合并来自 C3
.