Home
How to Effortlessly Redo Changes in Vim Using CTRL R
In the workflow of any developer or writer using Vim, making mistakes is inevitable. While most users quickly learn that pressing u in Normal mode will undo their last action, the method to "undo the undo"—commonly known as Redo—is often the first hurdle for those transitioning from modern graphical editors.
The immediate answer to the question of how to redo in Vim is the keyboard shortcut Ctrl + R. This command allows you to move forward in your edit history, effectively re-applying changes that were previously removed by an undo command. However, beneath this simple shortcut lies one of the most sophisticated undo systems in the software world: the Vim Undo Tree. Unlike the linear undo history found in editors like VS Code or Sublime Text, Vim tracks every state your file has ever been in, ensuring that no edit is ever truly lost.
Basic Commands for Redoing Changes
To perform a standard redo in Vim, you must ensure you are in Normal mode. If you are currently typing text, press Esc to exit Insert mode before attempting these commands.
Using the Ctrl R Shortcut
The most common way to redo is holding the Ctrl key and pressing r. Each time you press this combination, Vim moves one step forward in the undo history. If you have undone five changes using u, pressing Ctrl + R five times will bring your document back to the state it was in before you started undoing.
Executing Redo with Command Line
For users who prefer using the command line at the bottom of the screen, you can type :red or :redo and press Enter. This performs the exact same action as Ctrl + R. While slower for single changes, it is useful in scripts or complex command chains.
Applying Counts to Redo
One of Vim's strongest features is the ability to prefix commands with numbers. If you know exactly how many steps you want to redo, you can type the number before the command. For example, typing 10 then pressing Ctrl + R will redo the last ten undone changes instantly. This is significantly more efficient than mashing the keyboard ten times.
Understanding the Difference Between Small u and Capital U
In Vim, the lowercase u and the uppercase U serve distinct purposes, and confusing them can lead to frustration when trying to manage your document's state.
The Standard Undo u
The u command undoes the single most recent "change." In Vim, a change is defined as a sequence of actions that modify the buffer, such as a single Insert mode session, a deletion command like dw, or a replacement command.
The Line Undo U
The uppercase U is a specialized command. It reverts all changes made to the current line since you moved your cursor onto it. If you edit a line multiple times, pressing U once will return that specific line to its original state from the moment your cursor arrived there.
The unique characteristic of U is that the U command itself is considered a "change" in the undo history. This means you can actually use u to undo a U command. If you accidentally revert a line with U, pressing u will bring back your edits. This is a subtle but powerful distinction that highlights the non-linear nature of Vim's history.
Moving Beyond Linear History with the Vim Undo Tree
Most text editors use a linear undo model. If you make ten changes, undo five of them, and then make a new change, the five changes you originally "undid" are discarded forever. They are replaced by the new branch of history. Vim operates differently by implementing an Undo Tree.
How the Tree Structure Works
When you undo a few steps and then perform a new edit, Vim does not overwrite the previous history. Instead, it creates a new branch in the tree. The old path (the changes you undid) still exists in the memory.
Imagine the following scenario:
- You write a function.
- You undo the function.
- You write a different function.
In a standard editor, the first function is gone. In Vim, the first function is simply on a different branch of the tree. This architecture is why "undoing the undo" in Vim can sometimes feel more complex but is ultimately much safer for your data.
Visualizing the Tree
While Vim does not provide a built-in graphical tree in the terminal, you can see a text-based list of the branches by typing :undolist. This command displays the leaf nodes of the tree, showing you how many changes are in each branch and when they were made.
Navigating Undo Branches with g Minus and g Plus
Because Vim's history is a tree and not a line, u and Ctrl + R only move you up and down the current branch. To jump between different branches of history—allowing you to recover those "lost" edits that would be gone in other editors—you use the g- and g+ commands.
Moving Back in Time with g-
The g- command moves to an older state of the text, regardless of which branch that state is on. While u follows the logic of the tree, g- follows the chronological order of your edits. If you find yourself in a situation where u says "Already at oldest change" but you know you had code there earlier, try pressing g-.
Moving Forward in Time with g+
Conversely, g+ moves to a newer state of the text chronologically. If you have been jumping around branches and want to return to your most recent edit, g+ will navigate through the temporal sequence of changes until you reach the latest version of the file.
Chronological Undo with Earlier and Later Commands
Vim takes time-based navigation a step further with the :earlier and :later commands. These are incredibly intuitive for developers who think in terms of time rather than "number of changes."
Traveling Back to a Specific Time
If you realize that your code was working perfectly ten minutes ago but you have made a mess since then, you can use:
:earlier 10m
Vim will automatically navigate the undo tree to find the state the file was in exactly ten minutes ago. You can use various units:
sfor seconds (e.g.,:earlier 30s)mfor minuteshfor hoursdfor days (if you have persistent undo enabled)
Undoing Based on File Writes
You can also revert to the state the file was in during a previous save (write) operation:
:earlier 1f
This command takes you back to the state of the last time the file was written to disk. This is often more reliable than trying to count individual undos when you know the "last saved" version was stable.
Reversing Time Travel
If you go back too far, simply use the :later command with the same time syntax:
:later 5m
This will move the document forward five minutes in the edit history.
Managing Undo Blocks in Insert Mode
One common complaint from new Vim users is that if they spend 30 minutes in Insert mode writing a long paragraph and then press u, the entire paragraph disappears. This happens because Vim treats everything typed between entering Insert mode and exiting it as a single "change."
Creating Manual Breakpoints
You can create "undo breakpoints" without leaving Insert mode by pressing Ctrl + G followed by u. This tells Vim to end the current undo block and start a new one. In my personal workflow, I have mapped certain keys to do this automatically. For example, you can configure Vim to start a new undo block every time you press Enter or Backspace.
Recommended Configurations
By adding the following lines to your .vimrc, you can make your undo history more granular:
inoremap <C-U> <C-G>u<C-U>
inoremap <C-W> <C-G>u<C-W>
These mappings ensure that if you use Ctrl + U to delete a line or Ctrl + W to delete a word while typing, those deletions are stored as separate undoable actions, allowing you to recover them more easily with u.
Enabling Persistent Undo Across Different Sessions
By default, Vim's undo history is stored in memory. This means that if you close Vim and reopen it, your undo history is wiped out. You cannot "undo the undo" from yesterday's session unless you enable persistent undo.
The Power of Undo Files
Persistent undo saves the entire undo tree to a hidden file on your hard drive. This allows you to reopen a file weeks later and still use u, Ctrl + R, or :earlier 2d to navigate your previous edits.
Setting Up Persistent Undo
To enable this feature, you need to modify your .vimrc file. It is recommended to create a specific directory for these files so they don't clutter your working directories.