使用 vimdiff 合并更改

Merge changes using vimdiff

在我的例子中,我有两个文件 file1 和 file2。使用 vimdiff,我想按如下方式合并更改:

  1. 在第一个区别中,将 file1 中的行放在 file2 中的行上方。这意味着差异如file2中的Listing 2List 2应该是List 2,然后是合并文件中的Listing 2
  2. 在另一个变化中反转大小写。

快照如下所示。

我们如何使用 vimdiff 实现这一点?

可以通过Ctrlww[=在两个windows之间来回切换21=]。您可以从一个 window 复制一个 Ctrlww,然后粘贴到另一个。当您解决分歧时,亮点会改变并消失。

看看这个video

您可以在 windows 之间切换并复制和粘贴以解决差异,正如@David W. 在他的回答中建议的那样,但是 Vim 也有专门的 :diffput:diffget 命令来简化这个。使用这些(或相应的普通模式dodp命令),您不必在windows之间切换,并且范围默认为当前更改。

如果你需要添加而不是覆盖其他缓冲区的差异(这在经典的双向差异中是一个相当不寻常的情况),你仍然必须yank 原始行并 put 它们在 :diffget.

之后

一个地方完成后,可以使用]c[c命令跳转到下一个不同点。

您可以使用以下基本命令进行合并:

  • do - 从其他 window 获取更改到当前 window .

  • dp - 将当前 window 的更改放入另一个 window.

  • ]c - 跳转到下一个更改。

  • [c - 跳转到上一个更改。

  • zo - 打开折叠线。

  • zc - 关闭折叠线。

  • zr - 完全展开两个文件。

  • zm - 完全折叠两个文件。

  • Ctrlww - 改变window .

  • :only | wq - 退出其他windows,写入并退出。

需要注意的怪癖

  • dod p 如果您在正常模式下进行更改(或仅更改一行下的一行),但在可视模式下则不工作。

  • 撤消命令仅在已更改的缓冲区中有效,因此如果您使用 dp 和改变主意,您需要切换到另一个缓冲区才能撤消。

  • :diffupdate 将重新扫描文件以进行更改(Vim 可能会混淆,并显示虚假内容)。

可视化模式和更细粒度的控制

在可视模式下 select 编辑文本行时,您必须使用普通命令:

  • :'<,'>diffget
  • :'<,'>diffput.

例如:

  1. 进入可视模式并标记一些text/lines。
  2. 然后键入 :diffput 将 selected 行推送到另一个文件或 :diffget 从另一个文件中获取 selected 行。

要强调这一点:这意味着如果有一个由多行组成的更改块,那么 select 一个行的子集并发布 :diffput 将只应用这些更改其他缓冲区。

:diffget:diffput 也接受范围,有关更多信息,请参阅 :h copy-diffs。)

比较内部的两个缓冲区 Vim

如果您分块加载两个文件(:vs:sp),您可以在每个 window 上执行 :diffthis 并实现文件差异已经加载到缓冲区中。

:diffoff可用于关闭diff模式

This Vimcasts post and video 在实践中证明这一点。

如何在缓冲区之间应用所有更改

  1. 确保所有参与的缓冲区都处于 diff 模式(参见 :h start-vimdiff

  2. 一个。获取从缓冲区到当前缓冲区的更改: :%diffget <buffer-number>

  3. b.将当前缓冲区的所有更改放入另一个缓冲区: :%diffput <buffer-number>

:% 是 select 整个文件的范围;参见 :h :%:ls 将显示当前打开的缓冲区。)

我正在使用以下映射来处理三向合并(当 conflictstyle=diff3 时)

  nnoremap g1 :<C-U>call MergeKeepLeft()<CR>
  nnoremap g2 :<C-U>call MergeKeepBoth()<CR>
  nnoremap g3 :<C-U>call MergeKeepRight()<CR>

  function! MergeKeepLeft()
    let lastsearch = @/
    let @/ = '<<<<<<<'
    execute "normal! ?\<cr>dd"

    let @/ = '|||||||'
    execute "normal! /\<cr>V"

    let @/ = '>>>>>>>'
    execute "normal! /\<cr>d"

    let @/ = lastsearch
  endfunction

  function! MergeKeepBoth()
    let lastsearch = @/
    let @/ = '<<<<<<<'
    execute "normal! ?\<cr>dd"

    let @/ = '|||||||'
    execute "normal! /\<cr>V"

    let @/ = '======='
    execute "normal! /\<cr>d"

    let @/ = '>>>>>>>'
    execute "normal! /\<cr>dd"

    let @/ = lastsearch
  endfunction

  function! MergeKeepRight()
    let lastsearch = @/
    let @/ = '<<<<<<<'
    execute "normal! ?\<cr>V"

    let @/ = '======='
    execute "normal! /\<cr>d"

    let @/ = '>>>>>>>'
    execute "normal! /\<cr>dd"

    let @/ = lastsearch
  endfunction