Skip to content
| Marketplace
Sign in
Visual Studio Code>SCM Providers>Super UndoNew to Visual Studio Code? Get it now.
Super Undo

Super Undo

Mehrad Amiri

|
2 installs
| (0) | Free
Undo you can see before you take it. Every save is a version, in a list you can browse — arrow through it and read each change as a diff, then apply the one you want.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

Super Undo

Super Undo

CI License: MIT

Undo you can see before you take it. A VS Code extension.

Cmd+Z is a guess. You hold it down, watch the file flicker backwards, and hope you stop in the right place — and whatever it took away is off the screen before you can read it. Overshoot and you are redoing your way forward, guessing again.

Super Undo replaces the guess with a list and a diff. Every save is a version. Cmd+Alt+Z opens every version of the current file beside your code, newest first, and arrowing through that list shows you each one diffed against what is on screen right now. You read the change before you accept it, you jump straight to the version you want instead of stepping through everything in between, and nothing is written to the file until you say so.

Versions are stored in a shadow git repository outside your project — which is what makes the list long enough to be worth having. Your own repo, branches, staging area and commit history are never touched.

Installing

Not on the Marketplace yet. Build a .vsix and install it:

git clone https://github.com/mehradamiri/super-undo.git
cd super-undo
npm install
npx @vscode/vsce package
code --install-extension super-undo-0.1.0.vsix

Requires VS Code 1.100 or newer and git 2.32 or newer.

Using it

Action Keybinding
Undo — list every version of this file Cmd+Alt+Z / Ctrl+Alt+Z
Apply the version you are looking at Cmd+Alt+Enter / Ctrl+Alt+Enter
Browse recent changes across the workspace Cmd+Alt+R / Ctrl+Alt+R

The list lives in the File History panel in the sidebar, each row carrying +/− line counts and how long ago that version was saved — enough to recognise the change you are looking for before you open it. It sits beside your code rather than on top of it, so the history and the diff are readable at the same time.

The keyboard lands in that list, on the newest version that actually differs from what is on screen, with its diff already open. Arrow up and down and the diff follows the selection, so you read your way back through the file rather than guessing how far to go. The version you are looking at is coloured and marked with a ●, which the selection highlight cannot tell you — that only says where the keyboard is, and it fades as soon as you click into the diff. Cmd+Alt+Enter applies whichever version you are looking at, and the ✓ on a row does the same with the mouse.

When you apply a version it becomes an ordinary unsaved edit, so a plain Cmd+Z still reverses it and nothing reaches disk until you save. Set superUndo.applyAndSave if you would rather it save immediately.

Backing out of the list costs nothing, so there is no wrong place to look. A browse leaves no trace: any version diffs VS Code tries to restore after a restart are closed on startup, so a session always begins on your actual files rather than on a stale view of an old one.

The Super Undo view in the activity bar holds four panels:

  • Recent Changes — every file that changed recently, each showing its last five versions with +/− line counts. This is the whole-workspace view: what happened where, without having to open each file to find out.
  • File History — every stored version of the active file, and where Cmd+Alt+Z puts you. Select two entries to diff them against each other, or pin one so it is never thinned away.
  • Deleted Files — files you deleted, restorable with one click. Content is captured before the delete goes through and is exempt from thinning.
  • What Gets Tracked — a checkbox tree of your workspace.

Recent changes

Cmd+Alt+R opens the same information as a picker, grouped by file, with the diff following your selection — arrow through it to read each change, Enter to keep the diff open, or the ✓ button to apply one on the spot. Typing filters by file name.

Five versions per file is a default, not a rule. Change it with superUndo.recentCount, or from the list icon in the Recent Changes title bar, and any file with more history than that grows an Older versions… row that opens its full list. Every row supports the same actions as File History: diff, apply, apply-and-save, pin, and select two to compare.

Renames are followed exactly, using the editor's own rename event rather than git's similarity guessing, so history survives a rename plus a large edit in the same move.

What gets tracked

Everything, until you say otherwise. Uncheck any folder or file in What Gets Tracked and it stops being versioned; the choice is written to superUndo.exclude in workspace settings, so it is visible, hand-editable and shareable with your team. The most specific rule wins, which means you can uncheck src, re-check src/app, and uncheck src/app/legacy again.

A handful of exclusions are seeded on first run — node_modules, .git, build output — and they show up as visibly unchecked boxes rather than invisible magic. Binary files and anything over superUndo.maxFileSizeKB are skipped.

On secrets: files your .gitignore excludes, such as .env, are tracked by default. They are the files git will never protect for you, which is exactly why they benefit most. The tradeoff is that their contents sit in plaintext in the extension's storage folder. The shield button in What Gets Tracked excludes the usual secret-bearing patterns in one click.

How it works

Each workspace folder gets a bare git repository under the extension's global storage, keyed by the folder's real path. Saves are debounced and coalesced, so Save All across twenty files is one snapshot, and a snapshot costs a fixed five git processes no matter how many files it covers:

hash-object --stdin-paths → update-index --index-info → write-tree → commit-tree → update-ref

If the resulting tree is identical to the previous one, nothing is written at all — that is what absorbs format-on-save and autosave churn.

Every snapshot is a parentless commit under its own ref, rather than a chain of commits. Reading one file's history means asking a single long-lived git cat-file --batch process what that path pointed at in each snapshot, which stays fast into the thousands of snapshots. It also makes thinning trivial: dropping a version is deleting a ref, with no history rewrite and no changed SHAs.

Content is stored byte for byte. All git filters, hooks and user configuration are disabled inside the shadow repo, so CRLF files, BOMs and unusual encodings come back exactly as they went in.

Retention

History is thinned as it ages rather than deleted:

Age Kept
Under 24 hours every save
Under a week one per hour
Under 90 days one per day
Older one per week, indefinitely

Nothing past the last tier is ever removed, and pinned versions, pre-delete captures and pre-rename captures are exempt from thinning entirely. Adjust the tiers with superUndo.retention, or run Super Undo: Thin History Now by hand. Super Undo: Show Storage Statistics reports snapshot counts and on-disk size.

Settings

Setting Default Meaning
superUndo.exclude build output, node_modules, .git Globs that are not versioned
superUndo.include [] Globs that override an exclusion
superUndo.maxFileSizeKB 2048 Skip files larger than this
superUndo.debounceMs 400 How long saves are coalesced
superUndo.recentCount 5 Changes shown per file in Recent Changes
superUndo.baselineOnOpen true Capture a file when first opened, so its first save has a "before"
superUndo.applyAndSave false Save immediately when applying a version
superUndo.retention 24h / 7d / 90d Thinning tiers
superUndo.storagePath global storage Where shadow repos live

Requirements

Git 2.32 or newer, discovered through VS Code's built-in git extension (so remote and WSL hosts work). No runtime dependencies beyond that.

Development

npm install
npm run compile     # or: npm run watch
npm run lint
npm test            # 63 tests, ~6s: unit tests plus an activation smoke test, no editor required

Press F5 to launch an Extension Development Host with the extension loaded.

The store layer (src/store, src/git, src/tracking/policy.ts) never imports vscode, so it is tested directly against a real git binary in a temp directory. Keep new storage logic on that side of the line — ARCHITECTURE.md explains why, along with the storage model, the write and read paths, and the invariants a change has to preserve. Read it before sending a patch.

Issues and pull requests are welcome. CI runs compile, lint and tests on Linux and macOS.

Known limits

  • Two windows open on the same folder share one shadow repo. Writes are safe — they are serialised through a cross-process lock — but the second window's history view may lag until it writes something itself.
  • Moving a project folder starts a fresh history, since repos are keyed by path.

License

MIT

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
© 2026 Microsoft