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
:undojointells 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
uwill 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
:undojoinis 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
:lockmarksto also preserve mark positions during multi-step edits