我正在将两个分支与共同的祖先合并:
> [branch1]
git merge branch2 --no-commit
# ... did merging for several files with conflicts
git merge branch2 -srecersive -Xignore-space-at-eol -- myfile.txt # not possible
我已经解决了我希望保留的文件中的几个合并冲突。现在有一个文件有冲突,因为换行符不同。如何使用ignore-space-at-eol
recursive
策略选项来使git忽略换行符冲突并使另一个文件出现冲突,即。{类似于git merge branch2 -srecursive -Xignore-space-at-eol -- myfilewithconflicts.txt
的东西。见图。我可以撤消合并文件(git checkout -m myfilewithconflicts.txt
)但是如何将其他策略应用于此文件?
答案 0 :(得分:3)
不幸的是,你不能。一旦处于冲突合并的中间,您必须完成该合并,或者完全中止,以开始另一次合并。这也不是你想要的("完成并开始一个新的"可以让你到那里,但它是错综复杂且容易出错的。)
Git真的应该有一个"暂停合并"工具让你以更干净的方式做到这一点。也许可以写一个,但我没有时间去做。
让我们从一些背景开始吧。此时的问题已经减少为对单个文件进行三向合并 - 但我们是如何到达这里的?
一个典型的Git合并 - 或者更准确地说,我采取了什么来调用真正的合并,而不是真正的合并"快进"主要通过git checkout
或git reset --hard
完成的操作 - 使用三个输入。您可以指定其中一个输入--theirs
提交。其他两个是隐式的:它们是当前或--ours
提交,以及合并策略计算的合并基础。此类合并的默认策略是您在两个示例命令-s recursive
中选择的策略。
这种合并的目标是结合工作。合并基础提交充当了您(在您的分支上,--ours
)做了一些工作的共同起点,并且他们(在他们的分支上,--theirs
)做了一些工作,Git现在应该将它们结合起来。由于你们都是从相同的提交开始的,这使得组合更容易:Git可以从合并库运行git diff
到你的提交,看你做了什么,以及第二个{{1从合并库到他们的提交,看看他们做了什么。
运行这两个diff命令(或它们的内部等价物)后,Git可以将每个基本文件与提交中的一个文件配对,并在其提交中使用一个文件。做差异和配对文件都是作为合并策略的一部分完成的,但它还没有完成:这个过程简单地减少了问题,直到现在必须为每组文件组合工作。
忽略新文件,重命名文件和已删除文件等棘手案例,我们现在有了合并策略,每个路径名 P:
git diff
提交中 P 的内容;和--ours
提交中 P 的内容。作为一个捷径,如果三个版本中的两个或三个内容相同,则合并没有任何内容,Git可以选择{{1}已经在索引中的版本或者将--theirs
版本放入索引中。
如果没有,但是 - 如果所有三个版本不同 - 则此特定文件需要实际合并。 Git将所有三个版本复制到索引中,在插槽1,2和3中为合并过程保留,并调用低级别,一次一个文件合并代码。此代码使用三个版本合并一个文件。这三个版本是现在存储在索引中的版本(我们可以在以后将这三个版本提取到工作树中,如果我们愿意的话,那就是它们的位置)。
当我们想到合并冲突时,我们会想到低级合并代码。实际上,如果低级代码能够在没有冲突的情况下合并,它会继续从删除索引中的三个版本, add 将合并后的文件改为阶段0条目,并继续进行,好像没有任何问题。只有在此失败时,低级别合并才会向工作树写入文件的冲突合并版本。它将所有三个输入留在索引中。
请注意,在上面的序列中,Git使用index / staging-area来存储每个冲突文件的三个版本,并使用工作树来存储停止时的组合版本。为此,Git必须以 clean 索引和工作树开头。如果索引和工作树开始时不干净,则此过程可能会破坏未保存的工作。
因此Git说" no"如果您尝试运行--ours
未解决的合并冲突,或未提交的索引或脏工作树。如果你中止现有的,正在进行的合并,那将擦除你到目前为止所做的一切,并重新设置你的索引和工作树,使它们干净 - 但这会消除你迄今为止所做的一切。
您唯一的另一个选择是完成合并标记所有已解决和提交的内容。但是这会在当前分支上创建一个新的提交。如果您随后开始第二次合并,则隐含的合并基础是您刚刚提交的提交,而不是您在先前提交期间拥有的原始合并基础。这意味着您必须保存合并提交,但随后使用--theirs
或等效项撤消它。这是一个棘手且容易出错的部分。
低级代码使用大多数git merge
选项,例如git reset
或-X
,或者您的-X ours
。如果我们可以直接访问这个低级代码,我们可以自己运行它。这样我们就可以为做的某个特定文件添加-X theirs
。
不幸的是,虽然是 -X ignore-space-at-eol
命令,但不 -X ignore-space-at-eol
使用的代码({{1}代码在git merge-file
中,它实现了低级合并,而不是实现git merge-recursive
的{{1}}。 merge-recursive
命令不接受ll-merge.c
选项。它 <{1}},merge-file.c
,甚至是git merge-file
。它调用 可以1>}的代码,但它没有设置它的命令行选项。如果它确实需要merge-file
,您将能够直接达到您想要的效果。