# Vim Undo History Lost - Recover Lost Changes and Prevent Data Loss

You've been editing a file for an hour, made a mistake somewhere along the way, and reached for u to undo. But instead of stepping back through your changes, Vim reports "Already at oldest change" or jumps to a state from much earlier than expected. The undo history you relied on has vanished or been truncated, and you're left trying to manually recreate work you thought was safely preserved.

Understanding Vim's Undo System

Vim maintains an undo tree, not just a linear history. Every edit creates a branch, and you can navigate this tree in multiple directions. This is powerful but can lead to confusion when the undo history appears to be lost.

Check the current undo state:

vim
:undolist

This shows all undo branches. If it shows nothing or very few entries, your undo history has been lost or truncated.

The u command moves backward in time. Ctrl+R moves forward. But if you save the file and quit Vim, that undo history is gone by default.

Why Undo History Gets Lost

Session End

By default, Vim stores undo information only in memory. When you close Vim, the undo history is discarded. This is the most common cause of lost undo history.

Buffer Reload

When Vim reloads a file from disk, the undo history for that buffer is reset:

vim
:e!          " Reload file, lose undo history
:edit! %     " Same effect

The ! forces the reload, discarding changes and undo history.

Swap File Issues

If Vim crashes or is killed, the .swp file might contain undo information. But recovering from a swap file doesn't always restore the full undo tree.

Memory Limits

Vim can run out of memory for undo history with very large files or extensive editing sessions. Check the limits:

vim
:set undolevels?

The default is usually 1000. Setting it too low truncates history:

vim
:set undolevels=100    " Keeps only 100 levels of undo

Solution 1: Persistent Undo

The most important fix is enabling persistent undo, which stores undo history to disk:

vim
set undofile
set undodir=~/.vim/undo

Create the undo directory:

bash
mkdir -p ~/.vim/undo

Now when you close Vim and reopen a file, u will undo changes from your previous session. The undo history is stored in a separate file, typically with .un~ extension in the specified directory.

A more robust configuration handles the directory creation automatically:

```vim " Create undo directory if it doesn't exist if !isdirectory($HOME . "/.vim/undo") call mkdir($HOME . "/.vim/undo", "p", 0700) endif

set undofile set undodir=~/.vim/undo set undolevels=1000 ```

The 0700 permissions ensure only you can read the undo files, which may contain sensitive data.

Choosing an Undo Directory

For project-specific undo history, store undo files in the project directory:

vim
set undodir=./.vim-undo//

The // at the end tells Vim to use the full path as the undo filename, preventing conflicts between files with the same name in different directories.

Solution 2: Recovering From Swap Files

If Vim crashed and you have a swap file, you might be able to recover some history. When you open a file with an existing swap file, Vim prompts you:

bash
Found a swap file by the name ".file.swp"
    [O]pen Read-Only, (E)dit anyway, (R)ecover, (D)elete it, (Q)uit:

Choose R to recover. This restores the file content, but undo history recovery depends on when the swap was written.

Increase swap file update frequency to capture more state:

vim
set updatecount=100    " Save swap every 100 characters typed
set updatetime=2000    " Save swap after 2 seconds of inactivity

Solution 3: Using Vim's Branching Undo

If you still have an active session but can't find your changes, they might be on a different undo branch. Vim's undo tree preserves all changes, but u only follows one branch.

Use the g- and g+ commands to navigate chronologically through all changes:

vim
g-    " Go to older state (chronological)
g+    " Go to newer state (chronological)

Unlike u, these don't follow the branch; they go back in time regardless of which branch the change was on.

Jump to a specific undo number:

vim
:undo 5    " Jump to undo state 5

Solution 4: Using Undo Branches Visually

The :undolist command shows available branches:

vim
:undolist

Output looks like:

bash
number changes  when               saved
     2     42  2026/04/03 10:30:15
     3     18  2026/04/03 10:35:22

Jump to a specific branch with its number:

vim
:undo 2

For a visual undo tree, consider the undotree plugin:

vim
Plug 'mbbill/undotree'

Then run :UndotreeToggle to see a visual representation of all branches, making it much easier to find lost changes.

Solution 5: Backup Files as Last Resort

Vim can create backups before writing. If you lost undo history, an older version of the file might help:

vim
:set backup?

If enabled, check for backup files:

bash
ls -la yourfile~
ls -la yourfile.bak

Enable backups for future recovery:

vim
set backup
set backupdir=~/.vim/backup

Create the backup directory:

bash
mkdir -p ~/.vim/backup

Preventing Future Loss

Combine all these features for maximum safety:

```vim " Persistent undo set undofile set undodir=~/.vim/undo set undolevels=1000

" Backup files set backup set backupdir=~/.vim/backup

" Swap files set directory=~/.vim/swap set updatecount=100 set updatetime=2000

" Create directories if needed for dir in ['undo', 'backup', 'swap'] let path = $HOME . '/.vim/' . dir if !isdirectory(path) call mkdir(path, 'p', 0700) endif endfor ```

This configuration ensures:

  • Undo history survives across sessions
  • You have backup copies of files before changes
  • Swap files are updated frequently
  • All state files are in organized, private directories

Testing Your Configuration

After setting up persistent undo, test it:

  1. 1.Create a test file and make several edits
  2. 2.Save the file with :w
  3. 3.Close Vim completely
  4. 4.Reopen the same file
  5. 5.Press u to undo

If your changes undo correctly, persistent undo is working.

The combination of persistent undo, regular backups, and understanding Vim's undo tree ensures you never lose work again. Once configured, these features work silently in the background, protecting your editing history across all sessions.