如何使用vimdiff解决冲突?

时间:2013-02-15 22:46:13

标签: git vim git-merge mergetool git-merge-conflict

我刚刚在git中将一个分支合并到我的主人中,我得到了Automatic merge failed; fix conflicts and then commit the result.现在我运行了git mergetool并且vimdiff打开了下面的图片。我不知道如何使用vimdiff。这里的每个小组意味着什么,我应该如何解决合并冲突?

enter image description here

3 个答案:

答案 0 :(得分:122)

所有四个缓冲区提供同一文件的不同视图。左上角缓冲区(LOCAL)是文件在目标分支中的显示方式(您要合并的内容)。右上角缓冲区(REMOTE)是文件在源分支(您要合并的位置)中的显示方式。中间缓冲区(BASE)是两者的共同祖先(因此您可以比较左右版本之间的分歧)。

我可能会在以下方面弄错。我认为合并冲突的根源是两个文件都改变了自BASE以来文件的相同部分; LOCAL已将引号从double更改为single,REMOTE也进行了相同的更改,但也将背景值从颜色更改为URL。 (我认为合并不够智能,不会注意到LOCAL的所有更改也存在于REMOTE中;它只知道LOCAL已经在REMOTE所在的相同位置进行了更改。

在任何情况下,底部缓冲区都包含您可以实际编辑的文件 - 位于工作目录中的文件。你可以做任何你喜欢的改变; vim向您展示它与每个顶视图的区别,顶视图是自动合并无法处理的区域。如果您不想更改REMOTE,请从LOCAL拉出更改。如果您更喜欢LOCAL更改,请从REMOTE中拉出更改。如果您认为REMOTE和LOCAL都错误,请从BASE拉出。如果你有更好的主意,做一些完全不同的事情!最后,您在此处所做的更改将是实际提交的更改。

答案 1 :(得分:44)

@Chepner的答案很棒,我想补充一些关于“我应该如何解决合并冲突”问题的部分细节。如果你在这种情况下研究如何实际使用vimdiff,它会在下面。

首先,要解决“中止所有内容”选项 - 如果您不想使用“vimdiff”并想要中止合并:按 Esc ,然后键入:qa!并点击输入。 (另见How to exit the Vim editor?)。 Git会询问合并是否完成,请回复n

如果你想使用vimdiff,这里有一些有用的快捷方式。这假设您了解Vim的基础知识(导航和插入/正常模式):

  • 导航到底部缓冲区(合并结果): Ctrl-W j
  • 使用 j / k 导航到下一个差异;或者,更好的是,使用] c [ c 分别导航到下一个和上一个差异
  • 在折叠时使用 z o 打开它,如果你想看到更多的背景
  • 对于每个差异,根据@Chepner的答案,您可以从本地,远程或基本版本获取代码,或者根据您的需要进行编辑和重做
    • 要从本地版本获取,请使用:diffget LO
    • 来自远程::diffget RE
    • 来自基地::diffget BA
    • 或者,如果您想自己编辑代码,请首先从local / remote / base获取一个版本,然后转到插入模式并编辑其余部分
  • 完成后,保存合并结果,然后退出所有窗口:wqa
  • 通常,git检测到合并已创建并创建合并提交

您可以在互联网上搜索其他vimdiff快捷方式。我发现这个有用:https://gist.github.com/hyamamoto/7783966

答案 2 :(得分:1)

如何使用vim -d区分(BASE和LOCAL)与(BASE和REMOTE)

解决合并冲突时,您要查看的最重要的事情之一是:

  • 我的新提交如何更改基本提交
  • 现有提交如何更改基本提交

然后尝试将它们放在一起。

虽然vimdiff可以很好地并排显示BASE,LOCAL和REMOTE的所有内容,但我无法从中清楚地看到与BASE分开的两个差异:

+--------------------------------+
| LOCAL  |     BASE     | REMOTE |
+--------------------------------+
|             MERGED             |
+--------------------------------+

为解决此问题,我注意到git mergetool正在运行vimdiff时,如果名为main.py的文件存在冲突,则git会为每个版本生成文件,命名为:

main_BASE_1367.py
main_LOCAL_1367.py
main_REMOTE_1367.py

main.py在同一目录中,其中1367是git mergetool的PID,因此是一个“随机”整数,如In a git merge conflict, what are the BACKUP, BASE, LOCAL, and REMOTE files that are generated?

所述

因此,要查看我想要的差异,我首先使用git status查找生成的文件,然后打开新的终端并在我关心的文件对之间进行vimdiff:

vim -d main_BASE_1367.py main_LOCAL_1367.py
vim -d main_BASE_1367.py main_REMOTE_1367.py

此信息与git mergetool一起可以帮助很多人快速了解发生的事情!

此外,即使在运行mergetool时,您也可以打开文件:

vim main.py

直接进行编辑,如果您觉得使用更大的编辑器窗口会更容易。

我想我们甚至可以进一步自动化操作,以自动打开所有这些文件,但是我还没有冒险。

直接跳转以合并冲突

]c跳到vimdiff中的下一个差异点时,那里并不总是存在合并冲突。

为此,我在~/.vimrc中加入了

# Git Merge conflict
nnoremap <leader>gm /\v^\<\<\<\<\<\<\< \|\=\=\=\=\=\=\=$\|\>\>\>\>\>\>\> /<cr>

直接找到冲突。