FizzBuzz Journal

Not really a blog, just some stuff that a future me might need to remember one day.

  1. Github
  2. Stackoverflow
  3. Twitter

Undo and redo in Vim

29 Jul 2015

I know u to undo and Ctrl-r to redo but what happens when my undo tree branches?

Undo tree branching, an example

Suppose you start with an empty file and start entering names one at a time:

bob
alice
jim

Then you decide you want to backtrack, so you hit u twice to remove jim and alice leaving just:

bob

At this point it’s easy to get back to all the previous states using either u to go back or Ctrl-r to go forward.

But then you carry on editing adding a few other names:

bob
dorothy
derek

So now what happens if you want to go back to the state of the file before the first undo? Well you would be out of luck if you are just relying on u and Ctrl-r because the undo tree has branched.

The solution(s)

So it looks like Vim has ‘lost’ some of our intermediate editing steps. But that isn’t really the case, the undo tree still every step we took, we just need the commands to navigate that tree.

###g- and g+ There are a couple of different ways to solve this problem. Perhaps the simplest method is to use the g- and g+ commands. These simply step back and forward through your changes in time order. So from any given point you can always get back to another change by repeatedly using g+ (eventually) regardless of whether it is in the current undo tree branch or not.

Using these commands can be a bit confusing - partly because it’s far more natural to navigate a single branch of the tree. But also because these commands appear to merge normal text changes with undo/redo operations into a single ‘change’.

###:undolist If you want to discover other (lost) branches in the undo tree you can use the :undolist command. This doesn’t list every change, only leaf nodes of the undo tree. Here is an example from the undo tree I generated writing this post:

number changes  when               saved
    45      44  18:34:38             6
    55      54  56 seconds ago

Here change number 45 represents a separate branch of the tree to the one I am currently on. Change number 55 is where I am now.

If I want to skip to the other branch I can use the undo command giving it a change number:

:undo 45

From here I could use u and Ctrl-r to move back and forth on that branch.

###:earlier and :later

These commands work much the same as g+ and g- when issued without an argument. However you can pass a time interval, suppose you want to go back 10 minutes:

:earlier 10m

This can be handy if you have a good idea of when you were in the desired state, personally I find it hard to guess times like this.