发布于 2026-01-06 1 阅读
0

使用 VIM 解决 Git 合并冲突

使用 VIM 解决 Git 合并冲突

一切都如此顺畅,你甚至会希望发生冲突。

图片来自pexels.com图片来自pexels.com

我使用 VIM
这些代码都是用 VIM 写的,我写的每一行代码也都是用 VIM 写的。Git
已经成为几乎所有技术人员的必备工具,合并冲突也常常是工作的一部分。

当两个人修改了文件中的同一行代码时,通常会发生冲突……
在这种情况下,Git 无法自动判断哪个版本是正确的。
冲突只会影响执行合并操作的开发人员,团队其他成员并不会察觉到冲突的存在。Git
会将该文件标记为存在冲突,并中止合并过程。
之后,开发人员需要负责解决冲突。——
Atlassian Git 教程

解决 Git 冲突一直是我个人的一大难题;要么我尝试忽略冲突,不进行 HEAD 上的合并/撤销操作,要么就随便找个蹩脚的办法。
后来我接受了冲突不可避免的事实,于是尝试了变基,甚至把默认合并方式设置为“单选”,以为git merge --rebase这样就能消除所有冲突。
但事实证明,变基并不能完全避免冲突;变基会将你的提交逐个应用到目标分支的 HEAD 上,
因此,变基往往会引入新的冲突,而这些冲突必须加以解决
git merge --continue


逃犯之路

Vim Fugitive 是@tpope开发的一款非常棒的插件
它的一大亮点是 Gstatus 和 Gdiff,让你可以像在终端或常用的 Git 界面中使用 `git status` 和 `git diff` 一样,查看项目的状态和差异。
在 Vim 中处理这些冲突也非常便捷:当编辑冲突文件时,如果使用 Gdiff,fugitive 会启动一个三向差异比较,将当前工作区文件包围起来。此时会出现两个新的缓冲区:一个用于目标分支(即你要合并到的分支),另一个用于合并分支(即你要合并到的分支)。

验证前文所述概念:如果我正在 master 分支上工作,并且想要将 staging 分支合并到 master 分支,我会运行 `git merge staging` 命令。
这里 master 是目标分支,staging 是合并分支。
这种术语定义对于后续参考至关重要,可以明确我们将选择哪个缓冲区来解决冲突。

以下是Drew Niel制作的一段精彩视频,描述了上述内容(实用 VIM)。


还有什么好说的呢?

上述方法需要使用不太方便的缓冲区系统,以及像 diffput 或 diffget 这样难以理解的命令,当我试图弄明白缓冲区名称的引用关系时,这些命令对我来说毫无意义。整个流程并不流畅,我感觉缺少了什么。
为了解决这个问题,我在 .vimrc 文件中集成了一些别名,这样解决冲突就变得轻松、流畅,最重要的是——直观;我不想思考我在做什么,我只想直接去做。此外,我希望它比我见过的任何其他同类工具都更好、更快,通过消除复杂性和不直观的操作流程来实现这一点。


我的补充

让我们回顾一下我对 .vimrc 文件所做的修改,以及它们在解决冲突时是如何发挥作用的:

" Fugitive Conflict Resolution
nnoremap <leader>gd :Gvdiff<CR>
nnoremap gdh :diffget //2<CR>
nnoremap gdl :diffget //3<CR>
Enter fullscreen mode Exit fullscreen mode

以上三行代码即可轻松解决冲突;
首先输入<leader>gd`<p>` git diff,它会创建一个如上所述的三向分割Gvdiff屏幕。在我的映射中,我使用`<p>` 将窗格垂直分割。如果您更喜欢水平视图,请省略 `v`:`<p> Gdiff`。
效果如下:

Git 三向差异Git 三向差异

请注意,中间窗格是我的当前工作区,左侧是 HEAD,如果我选择该选项,我的代码将如下所示,而右侧描述的是主分支状态。

为了确定我在 HEAD 分支上的更改,根据我的映射,我输入 gdh,其中 gd 代表 git diff,h 是 VIM 的左键。我特意省略了 leader 键,因为它是一个内部进程组合键。
选择 master 分支后,我的当前工作区变为:

在选择左侧带有原始 `gdh` endraw 的“工作区”窗格后选择左侧后,工作区窗格将显示gdh

请注意,左下角的实际命令提到了
:diffget //2fugitive 从缓冲区获取更改的方式,//2其名称中包含该命令。

为完善此流程,可添加以下有用内容:

  1. 可以使用[c`--back` 或]c`--search` 来跳转到下一个 Git 代码块(或待修复的冲突)。

  2. 当您对工作区感到满意时(通常是在所有冲突都解决之后),就可以只打开这个窗格了;我们可以使用 `--include "VIM"` 命令<C-w>o来告诉 VIM 的窗口管理器只保留当前窗格。

就这么简单。
习惯这个流程轻而易举,让解决冲突变得更加轻松(也更有趣)。


我叫奥默,是ProdOps的一名工程师。ProdOps是一家全球咨询公司,我们通过采用DevOps文化,以可靠、安全、简便的方式交付软件。欢迎在下方评论区留言,或者直接在Twitter上关注我@omergsr 如果您喜欢这篇文章,请点赞,这将有助于我更好地创作。

文章来源:https://dev.to/prodopsio/solving-git-merge-conflicts-with-vim-5275