Wer modal editiert, braucht zwei verlässliche Sicherheits-Mechanismen: einen, der aus jeder Situation in den Normal-Mode zurückführt, und einen, der jeden Edit-Schritt umkehrbar macht. Vim hat beides — und das Undo-System ist eine seiner unterschätzten Stärken. Statt einer linearen Undo-Kette führt Vim einen Baum von Edits, der jede Verzweigung mitschreibt: wer rückgängig macht, dann etwas Neues editiert und später beide Versionen vergleichen will, kann das ohne Versionskontrolle direkt im Editor tun. Mit set undofile werden diese Bäume sogar über Editor-Sessions hinweg persistent — ein Vim-Undo aus letzter Woche funktioniert nach dem Neustart. Dieser Artikel deckt die universellen Notbremsen Esc und Ctrl-c, alle Undo-/Redo-Varianten, das Zeilen-Undo U, persistent-undo und die Zeit-Reise-Befehle ab.

Esc und Ctrl-c als Notbremsen

In Vim gibt es zwei Tastenkombinationen, die aus praktisch jeder Situation sicher zurückführen:

  • Esc — bringt aus Insert, Visual, Replace, Select, Operator-pending und allen anderen Modi zurück in den Normal-Mode. Funktioniert auch dann, wenn ein mehrteiliger Befehl halb eingegeben ist (d ohne Motion, g ohne Folgezeichen).
  • Ctrl-c — wirkt ähnlich, mit einem Unterschied: er löst beim Verlassen des Insert-Mode keine InsertLeave-Autocommands aus. Vor allem nützlich, um eine laufende Operation mitten im Vorgang abzubrechen, ohne dass Save-Hooks oder Plugin-Trigger aktiviert werden.

Eine universelle Notbremse, die in keiner Situation falsch ist: zweimal Esc drücken. Wer komplett die Orientierung verloren hat — egal in welchem Modus, mit oder ohne laufenden Befehl —, kommt damit zurück in den Normal-Mode mit leerem Eingabe-Puffer.

text Typische Notbremse-Situationen
" Versehentlich im Replace-Mode statt Insert
<Esc>                  " zurück in Normal-Mode

" Halb eingegebenes d, dann unsicher was als Motion folgen sollte
<Esc>                  " bricht den ausstehenden Operator ab

" :s/foo/bar in der Command-Line, will doch nicht
<Esc>                  " bricht den Ex-Befehl ab, ohne ihn auszuführen

" Plugin hat ein Popup geöffnet, das man nicht erwartet
<Esc><Esc>             " schließt Popups, kehrt in Normal-Mode zurück

Wer eine laufende externe Shell-Operation abbrechen möchte (z. B. :!sleep 30), drückt Ctrl-c — das sendet ein SIGINT an den Subprozess. Esc würde hier nichts ausrichten, weil Vim auf das Subprozess-Ende wartet.

u und Ctrl-r — Undo und Redo

Die zwei zentralen Befehle:

TasteAktion
uundo — letzten Edit-Schritt rückgängig machen
Ctrl-rredo — den durch u rückgängig gemachten Schritt wiederherstellen

u ist im Normal-Mode der Standard-Undo, beliebig oft anwendbar. Mit einem Count gehen mehrere Schritte zurück: 5u macht fünf Schritte rückgängig. Analog für Redo: 3<C-r> stellt drei Schritte wieder her.

Eine Vim-Eigenheit: Was Vim als „einen Edit-Schritt" zählt, ist nicht ein einzelner Tastendruck. Vim gruppiert Tastendrücke zu Undo-Blöcken:

  • Ein Normal-Mode-Befehl mit allen Auswirkungen = ein Block (3dw ist ein Undo-Schritt).
  • Eine Insert-Mode-Phase zwischen i/a/o und <Esc> = ein Block (egal wie viel Text dazwischen).
  • Ein Ex-Befehl wie :s/foo/bar/g mit allen Ersetzungen = ein Block.

Konsequenz: Wer im Insert-Mode 500 Buchstaben tippt, ohne zwischendurch Esc zu drücken, macht alle 500 Buchstaben mit einem einzigen u rückgängig. Das ist meistens gewollt — kann aber überraschen, wenn man nur „die letzten paar Zeichen" wegnehmen will. Wer feinere Undo-Granularität haben will, drückt regelmäßig zwischendrin Esc und steigt mit einem neuen i wieder in Insert ein. Eine zweite Variante:

vim ~/.vimrc — Insert-Mode-Undo-Punkte
" Im Insert-Mode bei jedem Punkt, Komma, Semikolon oder Leerzeichen
" einen neuen Undo-Punkt setzen — feinere Granularität, ohne Esc-Reflex.
inoremap . .<C-g>u
inoremap , ,<C-g>u
inoremap ; ;<C-g>u
inoremap <Space> <Space><C-g>u

<C-g>u ist das Vim-Idiom für „starte einen neuen Undo-Block hier". Diese Mappings führen die normale Taste aus und setzen anschließend einen Trennpunkt.

U — die Zeilen-Undo-Eigenheit

Vim hat einen zweiten Undo-Befehl, der in dieser Form kein anderer Editor kennt: U (Großbuchstabe). Er macht alle Änderungen in der aktuellen Zeile rückgängig — vorausgesetzt, du hast die Zeile seit dem letzten Verlassen nicht verlassen.

text U in Aktion
" Zeile: "Hallo Welt"
" Cursor steht auf "H"

rWelt<Esc>          " "Hallo" wird zu "Wello"
                    " (zwei Zeichen ersetzt, Zeile sieht jetzt aus: "Welto Welt")

cwGuten<Esc>        " "Welto" zu "Guten" geändert
                    " (Zeile: "Guten Welt")

U                   " ALLE Änderungen seit dem Betreten der Zeile rückgängig
                    " (Zeile wieder: "Hallo Welt")

U ist nicht „undo des undo" und auch nicht das Inverse von u. Es ist eine eigenständige Operation, die sich nur auf die aktuelle Zeile bezieht — und nur funktioniert, solange du die Zeile nicht zwischendurch verlassen hast.

In der Praxis ist U ein Nischen-Werkzeug. Die meisten Anwender nutzen stattdessen mehrere u-Anwendungen oder springen direkt mit g- (siehe unten) zu einem früheren Stand. Sinnvoll ist U bei einer Reihe schneller Korrekturen an einer Zeile, die man komplett verwerfen will, ohne zu zählen, wie viele Schritte das waren.

Vims Undo-Baum

Andere Editoren führen Undo als lineare Kette: jeder Edit hängt am vorigen, Redo geht in die Gegenrichtung. Sobald man nach einem undo etwas Neues macht, ist der vorherige Redo-Pfad verloren — das nennt man „Redo zerstört".

Vim macht das anders. Vim führt einen Baum: jeder neue Edit nach einem undo startet einen neuen Branch, der vorige Pfad bleibt im Hintergrund erhalten. Damit hat man im Prinzip alle jemals editierten Versionen einer Datei verfügbar — beliebig viele Verzweigungen, beliebig tief.

Zur Demonstration: vier Edits, dann ein Branch:

text Undo-Baum visualisiert
Stand der Datei: leer
↓ tippe "Hallo"
Version A: "Hallo"
↓ tippe " Welt"
Version B: "Hallo Welt"
↓ u (undo)
zurück auf Version A: "Hallo"
↓ tippe " Du"           ← neuer Branch, B bleibt erhalten!
Version C: "Hallo Du"

Baum-Struktur:
leer → A → B
         ↘ C  (aktuell)

Klassischer Undo-Editor: nach „Hallo Du" wäre Version B („Hallo Welt") verloren. In Vim ist sie weiterhin abrufbar — über zwei Befehle:

TasteBedeutung
g-gehe zum nächst-älteren Edit (in der Zeit zurück)
g+gehe zum nächst-neueren Edit (in der Zeit vorwärts)

g- und g+ ignorieren die Baum-Struktur und folgen der chronologischen Reihenfolge aller Edits. In unserem Beispiel führt g- von Version C zur ältesten Version, dann zu B, dann zu A.

Wer den Baum lieber visuell sehen möchte, installiert das Plugin undotree — es zeigt den vollständigen Branch-Graphen mit Zeitstempeln und ermöglicht die Auswahl per Cursor. Dieses Werkzeug ist Thema im Kapitel Erweiterte Features.

Zeit-basiertes Undo: :earlier und :later

Vim erlaubt Zeit-Reisen durch die Edit-Historie über zwei Ex-Befehle, die g-/g+ mit Zeitangaben erweitern:

BefehlBedeutung
:earlier 5mgehe zu dem Stand, den die Datei vor 5 Minuten hatte
:earlier 30s… vor 30 Sekunden
:earlier 2h… vor 2 Stunden
:earlier 1d… vor 1 Tag (mit persistent-undo)
:earlier 10… 10 Edit-Schritte zurück
:earlier 10f… 10 File-Writes zurück
:later 5mdas Gegenstück: gehe 5 Minuten in die Zukunft

:earlier 5m ist im Alltag erstaunlich nützlich: „mach das, was ich in den letzten fünf Minuten getan habe, rückgängig" — ein hochpräziser Reset ohne Zählen. Mit persistent-undo (siehe nächster Abschnitt) funktioniert das sogar über Sessions hinweg, also „mach das rückgängig, was ich gestern getan habe".

text Zeit-Reisen mit :earlier
:earlier 10m           " 10 Minuten zurück
:earlier 1d            " einen Tag zurück (mit undofile)
:later 5m              " wieder 5 Minuten vor
:earlier 50            " 50 Edit-Schritte zurück

Persistent-Undo: undofile

Standardmäßig vergisst Vim den Undo-Baum, sobald man die Datei schließt. Mit der Option undofile wird er als versteckte Datei (<original>.un~ bzw. in einem konfigurierten Verzeichnis) persistent gespeichert und beim nächsten Öffnen wiederhergestellt:

vim ~/.vimrc — persistent-undo aktivieren
" Persistent-Undo aktivieren
set undofile

" Empfohlen: undo-Dateien zentral im ~/.vim/undo/-Verzeichnis ablegen,
" statt überall als <name>.un~ neben den Originalen. Sauberer.
set undodir=~/.vim/undo//

" Das Verzeichnis muss existieren — Vim legt es NICHT automatisch an.
" Einmalig: mkdir -p ~/.vim/undo

Das doppelte Slash am Ende von undodir ist Absicht: damit kodiert Vim den vollen Dateipfad in den Namen der Undo-Datei. Ohne den Doppel-Slash würden zwei Dateien mit dem gleichen Basisnamen (z. B. index.html in zwei verschiedenen Projekten) sich gegenseitig die Undo-Historie überschreiben.

Mit aktiviertem undofile gilt:

  • Vim merkt sich pro Datei den vollen Undo-Baum dauerhaft.
  • :earlier 1d springt zum Stand vor einem Tag — auch nach Neustart.
  • g- und g+ funktionieren über Sessions hinweg.
  • Branches bleiben erhalten — gestern verworfene Versionen sind heute weiter abrufbar.

Der Speicher-Overhead ist gering: typische .un~-Dateien sind wenige Kilobyte groß. Sicherheits-Hinweis: Undo-Dateien enthalten Klartext-Versionen alter Datei-Stände. Wer in einem Repo mit sensiblen Daten arbeitet, sollte sicherstellen, dass ~/.vim/undo/ nicht versehentlich in ein Backup oder einen Cloud-Sync rutscht.

Was Vim NICHT undoen kann

Es gibt drei Klassen von Operationen, die außerhalb des Undo-Systems liegen:

  • Schreib-Operationen mit :w — Vim speichert die Datei, aber das Schreiben selbst ist kein Undo-Schritt. Wer eine versehentliche Speicherung rückgängig machen will, holt sich den älteren Inhalt per u zurück und speichert erneut.
  • Externe Datei-Änderungen — wenn ein anderes Programm die Datei modifiziert (Git-Pull, externer Editor, Build-Tool), kennt Vim diese Änderungen nicht. Mit :e! lädt Vim die Datei neu — auch das ist kein Undo, sondern ein Reset.
  • Quittieren mit :q! — die ungespeicherten Änderungen sind danach weg. Vim wirft den Buffer raus, der Undo-Baum geht verloren (außer er ist persistent gespeichert via undofile und die Datei wurde zwischendurch mindestens einmal gespeichert).

Eine Praxis-Empfehlung: nach komplexen Refactorings öfter :w drücken. Jeder Save ist ein Sicherheitsnetz — und mit undofile ist jeder Save zusätzlich ein dauerhafter Wiederherstellungspunkt.

Praxis-Konfiguration

Ein vollständiges, robustes Undo-Setup für die ~/.vimrc:

vim ~/.vimrc — Undo-Konfiguration
" --- Undo-System ---

" Mehr Undo-Levels (Default ist 1000, was meist reicht).
" Mehr kostet ein wenig RAM, ist aber bei großen Refactorings nützlich.
set undolevels=10000

" Persistent-Undo: Baum bleibt über Sessions hinweg erhalten.
set undofile

" Zentrales Verzeichnis statt .un~-Dateien neben den Originalen.
" Doppel-Slash verhindert Kollisionen gleichnamiger Dateien.
set undodir=~/.vim/undo//

" Feinere Undo-Granularität im Insert-Mode an Satz-Trenner-Zeichen.
inoremap . .<C-g>u
inoremap , ,<C-g>u
inoremap ; ;<C-g>u
inoremap ! !<C-g>u
inoremap ? ?<C-g>u
inoremap <CR> <CR><C-g>u

Dazu einmalig in der Shell:

shell einmalige Vorbereitung
mkdir -p ~/.vim/undo

Mit dieser Konfiguration hast du Vim-Undo auf einem Niveau, das jeder andere Editor erst durch Versionskontrolle erreicht — und das in jeder Vim-Installation seit Version 7.3 (2010).

Besonderheiten

`Ctrl-c` ist nicht immer dasselbe wie `Esc`

Aus dem Insert-Mode bringen beide in den Normal-Mode zurück. Der Unterschied: Esc löst Autocommands für das InsertLeave-Event aus, Ctrl-c nicht. Plugins, die auf InsertLeave reagieren (Save-on-leave, Linter-Trigger, Diagnose-Refresh), werden bei Ctrl-c umgangen — meistens irrelevant, manchmal genau das, was man will.

`5u` und fünf Mal `u` sind identisch

Vims Count-Präfix gilt auch für u. 5u macht fünf Edit-Schritte rückgängig — exakt wie fünfmal u hintereinander. Bei größeren Reset-Operationen ist der Count die effizientere Schreibweise.

Insert-Mode zählt als EIN Undo-Schritt — ohne Aufteilung

Wer von i bis <Esc> 500 Zeichen tippt, hat im Default-Setup einen einzigen Undo-Schritt. u macht alle 500 auf einmal rückgängig. Die <C-g>u-Mappings aus der Konfiguration oben unterteilen diesen Block an Satzzeichen und Leerzeichen — granularer, ohne den Tippfluss zu unterbrechen.

`U` braucht eine unverlassene Zeile

Die Zeilen-Undo-Eigenheit U funktioniert nur, solange der Cursor seit dem letzten Edit-Anfang in derselben Zeile geblieben ist. Sobald man die Zeile verlässt (mit j/k, Suche, Sprung), ist U für diesen Edit-Block deaktiviert.

`:earlier 1d` braucht persistent-undo

Ohne set undofile hat Vim keinen Edit-Verlauf, der älter ist als die aktuelle Session. :earlier 1d geht dann nur soweit, wie die heutige Session reicht. Mit aktiviertem undofile sind Zeit-Sprünge über Tage und Wochen möglich.

undotree-Plugin als visueller Browser

mbbill/undotree zeigt den Vim-Undo-Baum als grafischen Buffer mit Verzweigungen, Zeitstempeln und Differenz-Vorschau. Wer den Baum-Aspekt von Vims Undo wirklich nutzen will, kommt um das Plugin schwer herum — ohne es bleibt der Baum unsichtbar, mit ihm ist es eine echte Zeit-Reise-Konsole.

Weiterführende Ressourcen

Externe Quellen

Verwandte Artikel

/ Weiter

Zurück zu Bedienkonzept

Zur Übersicht