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:

Linear history tree

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.

Undo and redo

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.

Undo and redo in a tree

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.

Undo and redo based on time

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:

Gundo.vim

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.

September 12, 2017

Free PDF guide

Sign up to our newsletter and download the "Foreign key constraints in DynamoDB" guide.


In this article