Vim

内容变更历史记录

VIM 会记录文本改变之前的状态。因此,你可以使用「撤销」操作 u 来取消更改,也可以通过「重做」操作 Ctrl + r 来恢复更改。

值得注意的是,VIM 采用 tree 数据结构来存储内容变更的历史记录,而不是采用 queue。你的每次改动都会成为存储为树的节点。而且,除了第一次改动(根节点),之后的每次改动都可以找到一个对应的父节点。每一个节点都会记录改动的内容和时间。其中,「分支」代表从任一节点到根节点的路径。当你进行了撤销操作,然后又输入了新的内容,这时候就相当于创建了分支。这个原理和 Git 中的 branch(分支)十分类似。

考虑以下这一系列按键操作:

ifoo<esc>
obar<esc>
obaz<esc>
u
oquux<exc>

那么现在,VIM 中会显示三行文本,分别是 "foo"、"bar" 和 "quux"。这时候,存储的树形结构如下:

     foo(1)
       /
    bar(2)
   /      \
baz(3)   quux(4)

这个树形结构共包含四次改动,括号中的数字就代表时间顺序。

现在,我们有两种方式遍历这个树结构。一种叫「按分支遍历」,一种叫「按时间遍历」。

撤销 u 与重做 Ctrl + r 操作是按分支遍历。对于上面的例子,现在我们有三行字符。这时候按 u 会回退到 "bar" 节点,如果再按一次 u 则会回退到 "foo" 节点。这时,如果我们按下 Ctrl + r 就会前进至 "bar" 节点,再按一次就回前进至 "quux" 节点。在这种方式下,我们无法访问到兄弟节点(即 "baz" 节点)。

与之对应的是按时间遍历,对应的按键是 g-g+。对于上面的例子,按下 g- 会首先回退到 "baz" 节点。再次按下 g- 会回退到 "bar" 节点。

命令/按键 执行效果
[count]u:undo [count] 回退到[count] 次改动之前
[count]<c-r>:redo [count] 重做[count] 次改动
U 回退至最新的改动
[count]g-:earlier [count]? 根据时间回退到[count] 次改动之前。"?" 为 "s"、"m"、"h"、"d" 或 "f"之一。例如,:earlier 2d 会回退到两天之前。:earlier 1f 则会回退到最近一次文件保存时的内容
[count]g+:later [count]? 类似g-,但方向相反

内容变更记录会储存在内存中,当 VIM 退出时就会清空。如果需要持久化存储内容变更记录,请参阅 备份文件,交换文件,撤销文件以及 viminfo 文件的处理 章节的内容。

如果你觉得这一部分的内容难以理解,请参阅 undotree,这是一个可视化管理内容变更历史记录的插件。类似的还有 vim-mundo

请参阅以下链接获取更多帮助:

:h undo.txt
:h usr_32