Vim Tips Wiki
Register
Advertisement

Proposed tip Please edit this page to improve it, or add your comments below (do not use the discussion page).

Please use new tips to discuss whether this page should be a permanent tip, or whether it should be merged to an existing tip.
created May 11, 2010 · complexity basic · author Chrisbra · version 7.0

This tip is deprecated for the following reasons:

Persistent undo is now a part of Vim with the release of Vim 7.3. Tip needs an update to reflect this but is otherwise very good.

Vim supports standard undo and redo, and also supports undo branches which allow you to undo some changes, then make a new change, while keeping all changes available in the undo tree. This tip provides an overview of how undo branches can be used.

What are undo branches?

Vim 7.0 and later support undo branches. This feature prevents the loss of changes, even if you switch back to an earlier state of your text and start editing there.

A change in this context is considered as all editing you have made while in insert mode, or a single editing command in normal or command-line mode. As soon as you leave insert mode a new change will start. It is important to leave insert mode so you will really create a new distinct change to which you can later move back, otherwise all changes that are done while you are in insert mode will be considered the same change. While in insert mode, you can also press Ctrl-G then u to break the undo sequence and start a new change. In fact, it is probably a good idea to automatically do this in some situations, for example so you can undo one inserted line at a time, so you can recover if you change your mind after pressing Ctrl-U in normal mode, or so you can execute a normal-mode command you accidentally entered in insert mode. Note, that some commands (CTRL-G u is one of these) will break your insert mode edits into multiple changes. See :help ins-special-special for details.

You can imagine the undo branches like a tree with the top node being the first change that you have made to your text. Whenever you undo some changes and make a new change you create a new node.

Using u in normal mode will undo your last change and move you through the tree upwards. In contrast redo (Ctrl-R) will move down through this tree of changes. This is the same, as was done before Version 7 was released and is backwards compatible with other vi clones.

But you can also move through the changes in the order they were made. Thus g- will move you to the previous change, regardless where it is situated in your undo tree. Further use of g- will move you to the chronological previous change. As g- moves backwards through the undo tree, g+ will move forward through all changes until the final state is reached.

Besides the use of g+ and g- you can also use the ex-commands :earlier and :later. Both commands optionally accept either a count or a an amount of time that you want to move, thus

:earlier 10

will move 10 changes backwards through the undo tree, and

:earlier 1h

will move to the state of the buffer as it existed 1 hour ago (use s for seconds, m for minutes, and h for hours), and then

:later 10

or

:later 1h

will restore the buffer to the latest state after moving backwards to a previous state.

Example

Suppose you start a new change.

You start by entering insert mode and entering '1 ' and leaving insert mode. Now enter insert mode again and enter '2 ' and leave insert mode. And finally start insert mode again and enter '3' and leave insert mode again. Your buffer will now contain

1 2 3

You can always check the number of the most recent change with:

:echo changenr()

This will output 3 since you have made 3 changes (started insert mode 3 times).

Now press u to undo one change, start insert mode again and change the buffer so it will look like this:

1 2 4

You have now branched from the previous version of your buffer and created a new undo branch. Using:

:echo changenr()

will output 4.

If you press u in normal mode you will move back to

1 2

A further undo using u will change the buffer to

1

and if you press u a final time, you'll have an empty buffer again, as this is the state at which you started. You are now back before change 1 and

:echo changenr()

outputs 0.

If you redo your changes using Ctrl-R, you will move to

1

then

1 2

and finally

1 2 4

Notice, that you never reached change number 3 in which the buffer contained '1 2 3'. You can however use the g- and :earlier commands to move back to that change. So if you now press g- or :earlier your buffer looks like this:

1 2 3

If you know to which change you want to jump, you can also use :undo to jump to the specified change.

Entering

:undo 1

will put your buffer back at:

1

Undolevels option

The number of changes that are remembered is controlled by the 'undolevels' option. This is a global option that defines how many changes for each buffer will be remembered and that you can travel back. So if you set it to 25, you can at most undo 25 changes. If you set it to -1 you will not be able to undo any changes!

Histwin plugin

Undo tree

A screenshot of the plugin

The histwin plugin provides an easy way to jump back to previous branches in your history.

It provides the command :UB to open a new window listing the different branches of the changes made. On each item in the list, if you press Enter, you will move back to that state in the history tree of your buffer.

Additionally, you can tag certain states using T on the item. If you press D, a diff window is shown allowing you to review all changes that have been made between your current state and the selected state. And as some kind of funny feature, you can even let Vim replay the changes that have been made from the beginning.

After installing the plugin, read its help on configuration and usage by entering :help histwin.txt.

Persistent undo patch

The persistent undo feature is now officially available with Vim 7.3. Before Vim 7.3 (or when Vim 7.3 is compiled without support for persistent undo) whenever you end Vim (or force the reloading of a buffer), you lose all undo history and so may accidentally lose data. The persistent undo feature (which should be included with a normal, big and huge built of Vim) provides the possibility to store the undo history persistently in a file and reload these files whenever you edit these files again.

To make use of the feature, you need to set 'undofile':

:set undofile

You can then use the new commands :wundo to write the undo history to the file and :rundo to read the undo history back. For each file that is edited, the undo tree will be saved in a separate file in the same directory to the file, that you edited as .filename.un~ similar to the way swap files are saved. If you like to save all undo-files in a separate direcotry, you can set the 'undodir' option to specify the directory that will contain all undo files. Whenever persistent undo is enabled the stored undotree will be read back when you start editing that file again.

Additionally Vim 7.3 allows to jump back to previous save states of your file. This can be done by using :earlier <nr>f and :later <nr>f where <nr> is the number of file write. The different number of file-writes can be seen in the saved column of the :undolist command. For exampel :earlier 1f would go back to the state where the text was, when it was last saved and :later 1f would move in the undo tree to the next newer state, where the file was saved.

The new option 'undoreload' now determines, if the text state will be saved, before the buffer is reloaded using e.g. :e!. This is set by default to the value of 10,000. This means the buffer contents will be stored in the undo tree, if the buffer contains less than 10,000 lines. For example if you edit a simple file, :echo changenr() will output, the current position in the undo tree. If you now reload the buffer using :e! and output :echo changenr(), you will notice, that a new change was created (but only, if the buffer contained less lines than the option of 'undoreload' specifies or the value of 'undoreload' is negative).

However, note that if a file is modified externally without Vim, Vim will not be able to read the undo history back when you start editing the file again and the undo tree information will be lost. There is no way to get it back.

References

See also

Comments

Advertisement