vimtricks.wiki Concise Vim tricks, one at a time.

How do I combine multiple Ex commands into a single undo step in Vim?

Answer

:undojoin

Explanation

When writing Vim scripts or running multiple Ex commands, each command normally creates a separate undo entry. :undojoin merges the next change with the previous one so that a single u undoes both. This is essential for scripting multi-step edits that should be treated as one atomic operation.

How it works

  • :undojoin tells Vim to join the next change to the previous undo block
  • It must be called between two changes — not before the first or after the last
  • After :undojoin, the next modification becomes part of the same undo entry as the previous one
  • Pressing u will then undo both changes at once

Example

Suppose you want a command that adds a header comment and a timestamp to a file as one undoable action:

:call append(0, '// Module header') | undojoin | call append(1, '// Updated: ' . strftime('%Y-%m-%d'))

Without :undojoin, pressing u would only undo the timestamp line. With it, u removes both lines in one step.

Another common use in mappings:

:nnoremap <leader>h :s/^/# /<CR>:undojoin<CR>j:s/^/# /<CR>

Tips

  • :undojoin is most useful inside functions, autocommands, and complex mappings
  • It cannot be used if there is no previous undo entry (Vim will report an error)
  • Works well with :lockmarks to also preserve mark positions during multi-step edits

Next

How do I ignore whitespace changes when using Vim's diff mode?