# Fix Vim Undo Tree File Not Removed When Buffer Closes

You notice your project directories filling up with .un~ files -- Vim's persistent undo tree files. These files are supposed to enable undo history across Vim sessions, but they are not being cleaned up when you delete the original file, and they accumulate over time.

Alternatively, you may find that the undo tree file is not being created at all, meaning your undo history is lost every time you close a buffer.

Understanding Persistent Undo

Vim's undo tree normally exists only in memory. When you close a file, the undo history is lost. Persistent undo saves the undo tree to disk so you can undo changes even after closing and reopening a file.

Enable persistent undo in your .vimrc:

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

The double trailing slash tells Vim to encode the full file path in the undo filename, preventing collisions.

The Cleanup Problem

When you delete the original file, the undo tree file remains:

bash
rm myfile.txt
# .un~ file still exists:
# ~/.vim/undo/%home%user%project%myfile.txt

This is by design -- Vim does not track file deletions to clean up undo files. Over time, these orphaned undo files accumulate.

Finding Orphaned Undo Files

Find undo files whose original files no longer exist:

bash
find ~/.vim/undo -type f | while read undo_file; do
    # Decode the path (Vim replaces / with %)
    original=$(echo "$undo_file" | sed 's|%|%25|g; s|%\(.\)|/\1|g')
    # Check if original exists
    if [ ! -f "$original" ]; then
        echo "Orphaned: $undo_file (original: $original)"
    fi
done

Cleaning Up Orphaned Undo Files

Remove all orphaned undo files:

```bash #!/bin/bash # clean-undo.sh undo_dir=~/.vim/undo count=0

for undo_file in "$undo_dir"/*; do [ -f "$undo_file" ] || continue

# Decode the Vim-encoded path original=$(echo "$undo_file" | sed 's|%|%25|g; s|%\(.\)|/\1|g')

if [ ! -f "$original" ]; then rm "$undo_file" count=$((count + 1)) fi done

echo "Removed $count orphaned undo files" ```

Run this periodically via cron:

bash
0 3 * * 0 /usr/local/bin/clean-undo.sh

Alternative: Use File-Specific Undo Files

If you prefer undo files to live next to the original files (easier to clean up), use:

vim
set undofile
" No undodir set = undo files created next to original

This creates .filename.un~ files in the same directory. When you delete the original file, you can clean up with:

bash
find . -name "*.un~" -delete

Or add it to your .gitignore:

bash
*.un~

Undo File Not Being Created

If set undofile is in your .vimrc but no undo files appear, check:

  1. 1.Directory permissions:
bash
ls -la ~/.vim/undo/
mkdir -p ~/.vim/undo
chmod 700 ~/.vim/undo
  1. 1.Filesystem is read-only or full:
bash
df -h ~/.vim/undo
  1. 1.Overridden by filetype plugin:
vim
:verbose set undofile?

This shows where undofile was last set and whether another script is overriding it.

Undo Tree Navigation

With persistent undo enabled, you can navigate the full undo tree:

vim
g-          " Older state (navigates undo tree, not just linear undo)
g+          " Newer state
:earlier 5m " Go to state 5 minutes ago
:earlier 1d " Go to state 1 day ago
:later 10s  " Go forward 10 seconds
:undolist   " Show all undo branches

The :undolist command shows:

bash
number changes  time
    16      52  04/08/2026 10:30:15
    17      54  04/08/2026 10:31:22
    18      58  04/08/2026 11:00:05

Each number represents a branch point in the undo tree. Use u 16 to jump to state 16, even if it is not the most recent state.

Memory and Performance

Persistent undo files can grow large for files with extensive editing history. Check file sizes:

bash
du -sh ~/.vim/undo/
du -sh ~/.vim/undo/* | sort -rh | head -10

If individual undo files exceed 1MB, consider increasing undolevels only for specific filetypes:

vim
autocmd FileType python setlocal undolevels=1000
autocmd FileType markdown setlocal undolevels=500

The default is 1000, which is sufficient for most use cases.