Undo in Vim

Undo & Redo

Sooner or later you’re going to make a mistake. I’m sorry to hit you with these hard truths, but well, we’ve just got to accept them and move on.

Before we get to any of these, remember that in a graphical Vim client like MacVim all your normal OS undo, redo commands like ⌘z and ⌘⇧z on the Mac will work just fine. The following commands are a little faster (some of them at least) and will work in the terminal too, but if you’re still just getting started I encourage you to come back to this section later. You don’t need these unless you’re working in terminal Vim.

Simple undo

u

Keep whacking it to undo more things.

Extra typing undo

For ages I only knew about this version. Boy did it suck. I have no idea why it exists.

:u or :un or :undo

Keep typing it to undo more things… and wonder why you don’t just whack the u key in normal mode instead.

Undo also takes a number so you could 12u although, who knows exactly what you’d get from 12u. How far back is 12 undos in the mind of Vim?

Nuclear undo!

:quit!

Quits and throws out all changes since your last save.

The ugly duckling

1’d rather not mention it, but there are a couple reasons you will accidentally do this so…

U will also undo, except… not really. In most apps you’ve got a history of undos and redos that you can go backwards and forwards in. U doesn’t take you back one step in the history like a normal undo. It creates a new step in the history, which is the opposite of the last step starts getting confusing when you’re going back and forth in history and things go away come back and go away again. I have never wanted this.

The documentation says

The “U” command is treated by undo/redo just like any other command. Thus a “u” command undoes a “U” command and a ‘CTRL-R’ command redoes it again. When mixing “U”, “u” and ‘CTRL-R’ you will notice that the “U” command will restore the situation of a line to before the previous “U” command. This may be confusing. Try it out to get used to it. The “U” command will always mark the buffer as changed. When “U” changes the buffer back to how it was without changes, it is still considered changed. Use “u” to undo changes until the buffer becomes unchanged.

“Try it out to get used to it.”… Just. No. Never in a decade of using vim have I said to myself “Damn, I wish I had a way to undo that wasn’t actually an undo.”

Undo Trees

Vim 7 introduced the idea of an Undo Tree. In most editors undo is just a list of items, you can go back and forth in that list with undo and redo, but if you go back a ways, and then start changing things, all that you would have gotten with redo, are lost. Vim’s different. It doesn’t store a list of changes. It stores a tree of changes. When you undo a bunch, and then start typing you are creating a branch in the tree; a different path of possibilities, but the changes you made, and then undid, are still there in case you need them.

So, how to you explore this tree of divergent possibilities? Well, there are some built in commands, but they can get confusing to use. My advise is to install the Undo tree plugin. It visualizes the tree of changes, when they happened, and what they are. It lets you jump back in forth along the tree by simply putting your cursor on one of the changes and hitting enter.

See plugins for instructions on using plugins.

Making undo less undoey

One problem with Vim’s undo is that the amount of stuff that’s undone is just too much. Frequently I’ll type in a sentence, then want to undo some of it, but when I whack u the entire sentence, or paragraph, just disappears. There doesn’t appear to be a good way to make undo more granular.

The “best” (something’s better than nothing I guess) option is to “break” the undo sequence by typing <CTRL>-g u. For example, if I wanted to type “hello world” but have undo only undo the “world” part I would type

ihello <CTRL>-g uworld<ESC>

or as tommcdo so helpful put it in this helpful Stack Overflow post.

i                           " Enter Insert mode
 Hello                      " Type 'Hello'
      <C-G>u                " Break the undo sequence
             world!         " Type ' world!'
                   <Esc>    " Return to Normal mode
                        u   " Undo

The rest of that post has an interesting little vim script “to create undo breaks when you start deleting text, and also when you start entering text again after a deletion”. I haven’t decided if that’s something I want or not.

The problem with this <CTRL>-g u thing is that if i knew I was going to type something I was about to undo I wouldn’t need to add an undo break.

Undoing an accidental tab closure.

I mentioned this in the buffers post, but it kinda applies here too. If you accidentally close a tab in a window without saving first, your changes aren’t lost. They’re still waiting for you in that buffer. Open a new tab. Launch the buffer explorer. Then load the unsaved buffer into the new tab.

Redo

<CTRL>r Control+r is your redo.

If you like lots of extra typing you can

:red or :redo or redo

And, as with undo, you can redo multiple levels. 4<CTRL>-r or :redo 4