git checkout:「theirs」和「ours」的详细含义

7
git checkout文档中写道:

--ours --theirs 当从索引中检出路径时,为未合并的路径检出第二阶段( ours )或第三阶段( theirs )。

在合并(merge),变基(rebase)和樱桃拣选(cherry-pick)期间,“第2阶段”和“第3阶段”的意思是什么?有没有一种方法在运行命令之前查询这些“阶段”,以确保它将检索正确的版本?
2个回答

7
这些内容在gitrevisions文档中有记录(尽管我认为并不是非常清晰):
一个冒号,可选择跟随阶段编号(0到3)和一个冒号,后跟路径,命名了索引中给定路径处的blob对象。 缺少阶段编号(及其后面的冒号)表示阶段0条目。 在合并期间,阶段1是共同祖先,阶段2是目标分支的版本(通常是当前分支),阶段3是正在合并的分支的版本。
对于这些内容,您需要添加关于git rebasegit cherry-pick如何工作的知识。
普通的cherry picking是很好定义的:“ours”是HEAD版本,即您所在的分支,“theirs”是您正在选择的提交。当您挑选单个提交时,一切都很明显:阶段#1是假定的共同祖先提交,1阶段#2是当前分支顶部的版本,阶段#3是您正在挑选的版本。
如果您挑选一系列提交,则仍然成立,只是迭代成立。例如,假设您要挑选三个提交。Git仅逐个执行这三个提交。在第一次挑选期间,阶段#2是您的分支顶部,阶段#3是挑选的第一个提交的版本。完成该提交挑选之后,git创建一个新提交,推进了您的分支顶部。然后,在第二个挑选期间,阶段#2是您的分支顶部,即您的第一个挑选所做的提交,而阶段#3是挑选的第二个提交的版本。最后一个提交会重复此操作。每次,阶段#3都是“their”版本。
然而,rebase有点棘手。在内部,它从您原始的分支开始,将您切换到一个新的匿名分支(“detached HEAD”)。然后,它运行git cherry-pick来从您的原始分支中挑选每个提交。这意味着“ours”是分离的HEAD版本,“theirs”是来自您原始分支的版本。就像cherry-pick一样,每个要挑选的提交都会迭代地重复执行此操作(在交互式rebase的情况下,在其中编辑pick行)。完成rebase之后,git只是移动分支标签,使您刚刚创建的新匿名分支成为您的代码。
简而言之,可以将rebase看作是“翻转我们/他们的设置”,但这是夸张的说法。更准确地说,第2个阶段是您新的、融合的代码,第3个阶段是您旧的代码。
第1个阶段根据定义就是合并基础。对于真正的合并,这是最佳的共同祖先提交,但是cherry-pick会强制使用被cherry-pick提交的父提交作为合并基础。(还原以类似的方式工作,只不过被“复制”的提交是父提交,“合并基础”是要还原的提交。)

1
当你挑选单个提交时,你说“阶段#1是共同的祖先”,我认为这是错误的。第一阶段是你正在挑选的提交的父节点。 - wds
@wds:是的,阶段1是合并基础,确实是要为cherry-pick挑选的提交的父提交。我会修复这个问题。 - torek
你对为什么rebase "ours"和"theirs"的反向含义进行描述非常好。我仍然认为git维护者选择的术语可怕且令人困惑,但至少通过你的解释我能够理解它。 - Michael Burr

3

Git合并文档(以及其他一些地方)解释了索引文件记录最多三个版本或阶段:

对于冲突路径,索引文件记录最多三个版本:第一阶段存储来自共同祖先的版本,第二阶段存储来自HEAD的版本,第三阶段存储来自MERGE_HEAD的版本(您可以使用git ls-files -u检查这些阶段)。工作树文件包含“合并”程序的结果;即具有熟悉冲突标记<<< === >>>的3路合并结果。

下面是显示典型Git合并中三个阶段的图示:

Common Ancestor -> C1  --- C2         <- MERGE_HEAD (Stage 3)
(Stage 1)             \
                        --- C3 --- C4 <- HEAD (Stage 2)

假设以 C4HEAD 的分支正在合并回以 C2 结尾的分支。
正如文档所述,您实际上可以通过键入以下内容查看阶段:
git ls-files -u

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接