GIT:git checkout --ours仍显示“both modified”

3

我正在尝试解决一些文件中的合并冲突

both modified:   myFile.h

我运行了这个命令:

git checkout --ours myFile.h

然后我运行了:

git status

它显示了这个:

both modified:   myFile.h

为什么还显示“both modified”?
1个回答

7
一些git checkout命令会解决合并冲突,采用你检出的版本,而有些则不会。这是其中一种不会解决冲突的情况。
因此,你必须手动标记冲突已解决,使用命令:git add myFile.h

为什么是这样的

合并(动作,即merge-as-a-verb)通过Git的索引(也称为暂存区或有时称为缓存)进行。索引对于每个将进入下一个提交的文件都有一个条目。通常,该条目仅包含一个文件,但索引每个条目有四个插槽,它们被编号。插槽零(0)是正常的“没有冲突,文件准备好提交”的插槽。插槽1、2和3仅在合并冲突期间使用,并包含合并基础版本(插槽1)、--ours版本(插槽2)和--theirs版本(插槽3)。
如果插槽零已填充,则其他三个插槽为空。如果任何其他插槽已填充,则插槽0为空,文件处于“冲突”状态。(可以只填充其他三个插槽中的两个,如add/add、modify/delete和rename/delete冲突的情况)。
当你运行git checkout commit -- path1时,Git将文件从给定的commit复制到插槽零,然后从插槽零复制到工作树。如果其他三个插槽已填充,则复制到插槽零会清除它们,因此文件现在已解决!
但是,当你运行git checkout --ours -- path时,Git不必将任何内容写入索引插槽0,它只能从插槽2获取文件的内容。因此,它会从插槽2复制到工作树,文件未得到解决。
请注意,这意味着您可以执行git checkout HEAD -- path来从HEAD提交提取文件,并将其写入槽零,从而解决问题并写入工作树。然而,这又有一个微妙的不同。假设在合并期间,Git决定对文件进行了重命名和修改。它已经考虑到了重命名:文件的名称是evil/zorg,而不是旧名称evil-zorg。如果您使用git checkout --ours,Git将提取以旧名称evil-zorg为名称的(HEAD)版本,并将其放置在新名称evil/zorg下。如果您使用git checkout HEAD,Git将找不到以新名称存储的文件!
(这又是Git让实现细节显现出来的情况 - 或者等效地说,把太多的东西塞到一个命令中。)
1使用--的原因是处理名称看起来像选项的文件。(例如,如果文件名为--theirs怎么办?)如果path部分看起来不像选项,则不需要--。但养成好习惯:每次都使用--,这样以后当您的文件名称确实类似于选项时,就不会感到惊讶了。

谢谢,这是一个非常有帮助的答案。@user2924482 我认为你应该将其标记为答案。 - Leonid Usov
1
给亲爱的git checkout --ours/--theirs旅行者们:@torek还写了另一个回答类似问题的帖子,其中包含更多关于git的详细信息:https://dev59.com/9lkS5IYBdhLWcg3wzZTB#39439137 - Andrew Keeton

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