Never lose a change again: Undo branches in Vim
Introduction to work with undo branches in Vim 7.0+.
I often find myself in a situation where I hit undo a couple of times to peek back in time, but losing the ability to redo my way back due to inserting some text by accident. This caused some unpleasant moments until I've learned about Vim's powerful undo/redo system.
Working with undo branches in vanilla Vim
Undo tree was introduced in Vim 7.0., from that version the history is stored in a tree rather than a stack. The root of the tree refers to the original version of the file (no changes), and every time you change something a new node is added to the graph. The latest leaf node represents the last change you have made.
For example, the history looks like the following if you add line after line without using undo:
The path from the latest leaf node to the root contains all the changes you've made to reach the current state of the file.
With undo (u
) and redo (<C-r>
) you can walk upwards and downwards this path.
Using these commands alone Vim behaves like most editors that have the usual undo stack. However, if you change something after an undo action, the tree grows a new branch rather than simply discarding the previous future elements.
Vim keeps all your changes, but with u
and <C-r>
you can't reach the nodes that
are outside the path to the root.
However, Vim has the ability to navigate the
changes in the order they were made. With g-
you can move to the previous item in time,
while g+
moves to the next one.
This can be a solution to the problem of the accidentally lost changes while undoing around:
hitting g-
in this case can take you back to the latest version you need.
Gundo
g-
and g+
is neat, however discovering the whole history graph with them might be inconvenient.
Gundo.vim provides an easy to use way to navigate in the undo branches.
It requires Python and a Vim built with Python support.
The plugin provides a nice graphical layout of the undo branches, making the navigation in the changes trivial:
I've mapped
the <leader>u
to toggle this view, and I also had to set the g:gundo_prefer_python3
to 1,
because I am using it with Python 3.
"Display the undo tree with <leader>u.
nnoremap <leader>u :GundoToggle<CR>
"Add this line if you are using Python 3.
let g:gundo_prefer_python3 = 1
Summary
Vim has a powerful undo/redo system that makes sure that you don't lose any changes. Use the g-
/ g+
if you get stuck with u
/ <C-r>
. If you need total control over your history don't forget to install
Gundo.vim.