Git是否使用另一个合并策略选项重新合并文件?

Git是否使用另一个合并策略选项重新合并文件?,git,git-merge,Git,Git Merge,我正在合并两个具有共同祖先的分支: > [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 我已经解决了我希望保留的文件中的几个合并冲突。现在有一个文件由于换行符不同而产生冲突。如何使git忽略换行

我正在合并两个具有共同祖先的分支:

> [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
我已经解决了我希望保留的文件中的几个合并冲突。现在有一个文件由于换行符不同而产生冲突。如何使git忽略换行符冲突,并使用
递归
策略的选项
在eol处忽略空格
,即类似于
git merge branch2-srecursive-Xignore space at eol--myfilewithconflicts.txt
。见图。我可以撤消对文件的合并(
git checkout-m myfilewithconflicts.txt
),但如何将另一种策略应用于此文件


不幸的是,你不能。一旦处于冲突的合并过程中,就必须完成该合并,或者完全中止它,以启动另一个合并。这两者都不是你想要的(“完成并开始一个新的”可以让你达到目的,但它是复杂且容易出错的)

Git真的应该有一个“暂停合并”工具,让您以更干净的方式完成这项工作。也许可以写一篇,但我没有时间写

为什么这么长 让我们从一些背景开始。此时的问题已经简化为对单个文件执行三方合并,但我们是如何做到这一点的

一个典型的Git合并,或者更准确地说,我称之为真正的合并,而不是真正的合并“快进”操作,它主要是通过
Git checkout
Git reset--hard
,使用三个输入。您可以指定其中一个输入,即
--theres
提交。另外两个是隐式的:它们是当前的或
--我们的
提交,以及由合并策略计算的合并基础。这种合并的默认策略是您在两个示例命令中选择的策略,
-s recursive

这种合并的目标是合并工作。合并基提交作为一个公共起点,您(在您的分支上,
--我们的
)做了一些工作,他们(在他们的分支上,
--他们的
)做了一些工作,Git现在应该合并这些工作。由于两人都是从同一个提交开始的,这使得组合更加容易:Git可以从合并基运行一个
Git diff
到您的提交,以查看您做了什么;从合并基运行第二个
Git diff
到他们的提交,以查看他们做了什么

运行了这两个diff命令(或它们的内部等效命令)之后,Git就可以将每个基本文件与提交中的一个文件配对,并与提交中的一个文件配对。进行差异和文件配对都是作为合并策略的一部分完成的,但还没有完成:这个过程只是简单地减少了问题,直到现在必须为每组文件合并工作

忽略新文件、重命名文件和删除文件等棘手的情况,我们现在有了合并策略,每个路径名p:

  • 查看合并库中P的内容
  • 查看
    --ours
    提交中P的内容;及
  • 查看
    --theres
    commit中P的内容
作为一条捷径,如果三个版本中有两个或三个的内容相同,那么就没有什么可以合并的,Git可以选择已经在索引中的
--我们的
版本,或者根据需要将
--他们的
版本放入索引中

如果不是,但如果所有三个版本都不同,则此特定文件需要实际合并。Git将所有三个版本复制到索引中,位于为合并进程保留的插槽1、2和3中,并调用低级的一次一个文件的合并代码。此代码使用三个版本合并一个文件。这三个版本是现在存储在索引中的版本(如果愿意,我们可以稍后自己将这三个版本提取到工作树中,但这就是它们所在的位置)

当我们想到合并冲突时,我们会想到低级合并代码。但是,事实上,如果低级代码能够合并而不发生冲突,它将继续从索引中删除这三个版本,将合并的文件添加为stage zero条目,并继续进行,就好像没有任何问题一样。只有当此操作失败时,低级合并才会将文件的冲突合并版本写入工作树。它将所有三个输入都保留在索引中

如果合并不完整,则无法启动新的合并 注意,在上面的序列中,Git使用索引/暂存区域存储每个冲突文件的三个版本,并在停止时使用工作树存储组合版本。为此,Git必须从一个干净的索引和工作树开始。如果索引和工作树一开始不干净,此过程可能会破坏未保存的工作

因此,如果您试图在存在未解决的合并冲突、未提交的索引或脏工作树的情况下运行
Git merge
,Git会说“否”。如果中止现有的、正在进行的合并,则会清除迄今为止所做的一切,并重新设置索引和工作树,使其保持干净,但会清除迄今为止所做的一切

您唯一的其他选择是完成合并标记所有已解决的内容并提交。但这会在当前分支上创建一个新的提交。如果随后开始第二次合并,则隐含的合并基础是您刚刚进行的提交,而不是您在先前提交期间拥有的原始合并基础。这意味着您必须保存合并提交,然后使用
git reset
或等效工具撤消它。这是一个棘手且容易出错的部分

如果我们能用不同的选项重复低级合并就好了 低级代码使用了大多数
-X
选项,如
-X我们的
-X他们的
,或者在您的情况下,
-X忽略eol处的空格
。如果我们可以直接访问这个低级代码,我们可以直接运行它