Learn how to use vim undo to time travel

May 9, 2020

Follow @learnvim for more Vim tips and tricks!

Vim's undo can do things that many text editors can't. It can travel across time, create branches in history, and preserve undo history. How cool is that?

In this article, you will learn about vim undo to boost productivity. What I'll cover:

  • Basic undo/ redo
  • Persistent undo
  • Undo tree
  • Time travel

Basic undo/redo

You can do basic undo with u and redo with Ctrl-r in normal mode.

For command-line alternatives, use:

:u[ndo]
:red[o]

Vim sets a maximum number of how many times you can undo in undolevels option. You can check it with :echo &undolevels (mine is set to be 1000 default). To change it to 2000, run :set undolevels=2000.

Persistent undo

When you close a text editor, normally you lose all your undo history. This means when you open that file again, you can't immediately undo.

However, vim can preserve your undo history inside an undo file with :wundo[!] myUndoFile.

Let's do a quick example. Create a file hello.txt. Type:

Hello one

Go back to normal mode, type another line below:

Hello two

Go back to normal mode, type another line below:

Hello three

Go back to normal mode.

If you undo once, it will remove "Hello three" line. Undoing twice will remove "Hello two" and "Hello three", etc. Again, everything works as expected. Let's redo everything until you get all your texts back.

Hello one
Hello two
Hello three

Create your undo file:

:wundo! hello.undo

Then exit vim. By now you have hello.txt and hello.undo in your directory. When you open up hello.txt again, you can't undo anything immediately. To restore our undo history, let's read from our undo file:

:rundo hello.undo

Your previous undo history is loaded. Now if you undo, vim will remove "Hello three". If you undo twice, vim will remove "Hello two" and "Hello three", etc. It's like you never closed vim!

Undo tree

Vim has an undo tree that grows every time you create an undo branch. I will explain what undo branch later.

Create another file hello2.txt. Type:

Hello one

Go back to normal mode, type another line below:

Hello two

Go back to normal mode.

If you undo once, it undoes "Hello two", leaving you with only "Hello one". Everything is good so far. Redo everything until you're back with "Hello one" and "Hello two".

Undo once to remove "Hello two" so you have only "Hello one".

This time, type "Hello three" below "Hello one". You now have:

Hello one
Hello three

Now if you undo, vim removes "Hello three", leaving you with only "Hello one". If you undo again, vim removes "Hello one", leaving you with blank file! You just created a branch in your undo history. You can't get your "Hello two" text back once you create an undo branch... or can we?

Redo everything until you get these texts back.

Hello one
Hello three

Now type g-. Voila! You get your old "Hello two" back.

Hello one
Hello two

Type g+. You get "Hello three" back.

Hello one
Hello three

What happened? When we still had "Hello one" and "Hello two" and did an undo once (losing "Hello two"), we typed "Hello three". A new undo branch was created. Every time you undo and make changes, Vim create a new undo branch. Have you seen a time-travel movie when the protagonist went back to the past and altered the future? It is somewhat similar to this. We went back to the past state with undo, modified a file, and altered the undo history.

Vim can go to different undo branches (or I should say "alternate reality") with g- and g+.

In addition, you can also do :earlier n or :later n, where n is the newer / later state number. To go back to 2 branches before, do :earlier 2.

To see all undo branches' leafs, you can do:

:undol[ist]

You should see something like this (yours may look slightly different from mine).

number changes  when               saved
     1       1  07:59:26
     4       2  07:59:43
     5       3  08:00:55

To repeat, every time you undo and make changes instead of redo, you create a new branch.

It is not intuitive at first. Play around with it.

Time travel

Vim can also travel to a state in the "past" and "future". The :earlier and :later commands accept time as an argument:

:earlier 5s     " go to older state 5 seconds before
:earlier 5m     " go to older state 5 minutes before
:earlier 5h     " go to older state 5 hours before
:earlier 5d     " go to older state 5 days before

You can use same argument on :later:

:later 5s     " go to newer state 5 seconds after
:later 5m     " go to newer state 5 minutes after
:later 5h     " go to newer state 5 hours after
:later 5d     " go to newer state 5 days after

Finally, you can tell vim to go to older state "5 saves ago" with :earlier 5f. and to later state "3 saves later" with :later 3f.

Conclusion

Vim has a powerful undo system.

It can have virtually unlimited undos (as many as your machine's memory permits) by setting undolevels.

It can create an undo file to preserve undo history with :wundo and :rundo.

Each time you undo and make different changes, you create a branch in your undo history. You can view these branches with :undol and travel with g- and g+.

:earlier and :later can be used to jump to different states based on: time, file writes, and undo branches.

Undo tree is not an easy concept to grasp initially. I still struggle to wrap my head completely around it. Play around with it to get the basics. It can be a powerful assets in your coding.

Thanks for reading. Now go and create a time paradox >=).