强制执行 'git merge' 声明所有差异为合并冲突

8
在“git merge”中,我希望任何差异,即使不是通常的合并冲突,也被视为合并冲突。然后,使用“git mergetool”,我可以查看和解决每一个差异。我尝试在.gitattributes中指定“* -merge”,但似乎没有起作用:
$ git checkout master
Switched to branch 'master'
$ ls
foo.c
$ git merge add-on
Updating a628824..2219552
Fast-forward
  0 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 bar.c
$ cat .gitattributes 
* -merge
$ ls
bar.c   foo.c

对于上述的“git合并插件”,我预期在没有基础版本、本地版本和远程版本的情况下,对于“bar.c”会出现合并冲突。[编辑]如一个回答中所建议的,上面并没有发生合并。这里是一个我强制合并的案例,但仍然没有达到预期的合并冲突。
$ git merge --no-ff add-on
Merge made by the 'recursive' strategy.
 0 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 bing.c

请注意,上述中的“bing.c”实际上是空的;但是,这并不是问题,因为提供非空文件仍然会被合并。[编辑2]我尝试使用--no-commit选项,结果如下:
$ git merge --no-ff --no-commit add-on
Automatic merge went well; stopped before committing as requested
$ git status
# On branch master
# Changes to be committed:
#
#   new file:   boom.c
#
$ git mergetool
No files need merging
$ cat .gitattributes 
* -merge

我还缺少什么?有没有办法确认“.gitattributes”是否正在被使用或读取?

3个回答

6
你并没有合并。你的命令 git merge add-on 执行了一个“快进”,这意味着它只是移动了分支头。这是因为你的 add-on 分支已经从你的 master 分支的尖端派生出来,所以不需要合并。如果你运行 git log,你会看到没有合并提交。
基本上,在合并之前,它看起来像这样:
              master
             /
o---o---o---o           add-on
             \         /
              o---o---o

合并操作只是将 master 指针移动到了最后一行:

                          master, add-on
                         /
o---o---o---o---o---o---o

如果想要强制合并,请传递--no-ff标志,如 git merge --no-ff add-on
经过进一步思考,merge属性不能做你想要的事情。这仅适用于文件级合并,这意味着合并的两个方面都对具体文件进行了更改。如果仅有一个方面发生更改(这是你的情况),则不会进行文件级合并,并且更改的文件将被无条件接受。
您最好的选择可能是使用git merge --no-ff --no-commit add-on来生成合并,但实际上不进行提交。现在您可以检查结果并将其调整到满意程度,然后再提交合并。如果要逐个块地接受更改,则可以执行git reset以重置索引,然后执行git add -p以进行逐个块的分段暂存。

2
谢谢。我尝试使用“git merge --no-ff add-on”再次合并,但仍然没有期望的合并冲突。 - GoZoner
@GoZoner:没有合并冲突,因为没有文件级别的合并。只有一个合并的一侧对文件进行了更改,因此该侧被无条件选择。当存在文件级别合并时(例如,双方都有更改并需要调用合并驱动程序),merge属性才适用。 - Lily Ballard
没错,但根据git属性文档中对于'merge unset'的说明,我预计会强制发生合并冲突。也许'* -merge'不是我想要的行为方式(即使通常可以合并的每个差异都会产生冲突,然后我可以使用三方合并显式地解决它,以便我可以验证合并在语义上是否正确,而不仅仅是文本上正确)。 - GoZoner
1
@GoZoner:从manpage中可以看到:“属性合并影响当需要进行git合并期间的文件级合并时,如何合并文件的三个版本”(我强调)。您没有文件级别的合并。我已经使用替代建议更新了我的答案。 - Lily Ballard
是的,现在看到并已确认。 - GoZoner

3

您可以尝试以下方法:

git merge --no-commit

如果你不想让GIT提交合并更改,可以选择以下选项。另外,如果你想在没有冲突时进行提交,但不想丢失源分支,则选择no-ff:

git merge --no-ff

如果必要,两者都可以使用。

更多信息请参见:为什么Git默认使用快进式合并?


谢谢。我尝试使用“git merge --no-ff add-on”再次合并,但仍然没有出现所需的合并冲突。 - GoZoner
你尝试过使用 --no-commit 吗?它不会自动提交,这样你就有机会选择接受哪些更改,哪些不接受。并不一定会出现 冲突,因为可能并没有冲突。 - yamen
我会尝试翻译,但请注意 gitattributes 的帮助文档中指出:“未设置:将当前分支的版本作为暂定合并结果,并声明合并存在冲突。这适用于没有明确定义合并语义的二进制文件。” 声明冲突应该在提交之前停止合并。 - GoZoner

2

我有类似的愿望,但是使用自动化工具无法实现。这里有一个半自动化的解决方案:

master 分支合并 add-on 分支,并手动解决冲突:

按照以下步骤开始:

git merge --no-ff --no-commit add-on

然后,对于每个更改的文件执行以下操作:

git show master:path/to/file > from_master
git show add-on/to/file > from_add-on
kdiff3 --qall from_master from_add-on -o path/to/file
git add path/to/file

最后,
git commit

为什么是90%的解决方案?

这个解决方案即使在“显而易见的情况”下也能合并,并且它不强制我设置.gitattributes,因此我可以根据我正在合并的人和原因来确定“手动合并”的行为,而不是根据我正在合并的文件。


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