Better Git VS Code
Fast, keyboard-driven Git review for the agentic age.
Install from the VS Code Marketplace
·
GitHub
AI can write a changeset in seconds. You still need to review every line. Better Git VS Code turns that review into one continuous loop inside VS Code: move through each change, inspect it in context, stage the file when it is right, and keep going without reaching for the mouse or hunting through Source Control.
The review loop
1. Jump between every Git change
One key flies to the next or previous change. At the end of a file, it continues into the next changed file automatically. No scrolling, clicking through the SCM tree, or losing your place in a large AI-generated changeset.
Option+. next · Option+, previous — literally the > / < keys, pointing the way.
2. Hold Shift to stage and continue
Approve as you go. Holding Shift on the nav key stages the file you're looking at and jumps you straight to the next unstaged change — so reviewing and staging become one continuous flow. No reaching for the mouse, no detour to the Source Control panel. Sweep through, approving each file with a flick of the same key.
Shift+Option+. stage & next · Shift+Option+, stage & previous.
3. Fix something without losing your place
When you open a staged file, what you see is a frozen, read-only snapshot of what's staged — you can't actually edit it there. Spot a bug mid-review and you'd normally have to go hunt down the real file. One key does it for you: it opens the actual, editable working file at the exact line and scroll position you were looking at. See it, fix it, on the spot.
Option+R — open & reveal the real file (remap to anything you like; see overrides below).
That is the core workflow. The same navigation keys also handle the awkward cases that ordinary hunk navigation skips: brand-new files and changes larger than the editor viewport.
Generate commit messages with Codex or Claude — no Copilot subscription
Click Generate Commit Message with AI ($(sparkle)) in a Git repository's Source Control header, choose it from the Commit dropdown, or run it from the Command Palette. On first use, Better Git detects the Codex and Claude Code CLIs in your configured paths, VS Code's PATH, and a small set of standard macOS install locations. It shows the detected options instead of silently choosing an account, then saves your selection globally. Run Better Git: Change Commit Message AI Provider whenever you want to switch.
Better Git uses the already-signed-in local CLI, so it does not need GitHub Copilot or a separate API key. Codex uses explicitly pinned none reasoning; Claude uses low effort. Both receive schema-validated, bounded change context from an otherwise empty temporary workspace. Codex runs ephemerally in a read-only sandbox. Claude runs without tools, settings sources, or session persistence.
If the repository has staged changes, only the staged diff is used. With nothing staged, Better Git uses the working-tree diff and untracked files instead. The generated text fills the selected repository's commit-message box and never commits for you. If you type in the box while generation is running, Better Git will not overwrite your text without asking.
VS Code's literal sparkle inside the right edge of the commit-message box belongs to the proposed scm/inputBox API, which Marketplace extensions are not permitted to use. Better Git therefore puts its AI sparkle in the nearest supported Source Control surfaces instead of patching VS Code or hijacking Copilot's command. If VS Code cannot find a CLI, set Codex Executable Path (better-git-vscode.codexExecutablePath) or Claude Executable Path (better-git-vscode.claudeExecutablePath) to its absolute path.
Review edge cases without leaving the keyboard
Read every line of brand-new files
Reviewing an AI changeset that adds whole new files? A brand-new file is one big new-diff with no per-change hunks to jump between, so change-navigation used to fly straight past it — you never actually read it. Now, on a fully-added file (untracked / staged-new), the next/previous-change keys step the cursor a few lines at a time so you page through and review the entire file, then roll on to the next change as usual. Tune the step with better-git-vscode.newFileNavLineJump (default 5). Modified files are never affected — they always navigate change-to-change.
Some hunks run below the visible screen. One press of next-change can land near the bottom — and the rest runs off-screen, so you'd have to take your hands off the keyboard, scroll, then press next again. Large replacements are especially awkward because Git and VS Code can divide the same visual change differently: native navigation may leap dozens of lines or move to the next file while the broader replacement still has unread content. Better Git retains that broader hunk boundary and steps through it before accepting an oversized jump or rollover.
Hunks whose complete rendered range is already visible are untouched — one press still jumps straight to the next/previous hunk. Anything unread moves by exactly ten logical lines per press by default; the final partial step lands on and presents the exact hunk edge, and only the following press may leave it. previous-change mirrors the same contract, including direction reversal from the current caret. Set better-git-vscode.hunkStagingLineStep to any positive custom step, or 0 for viewport-minus-overlap auto mode. Tune the engage threshold with hunkStagingThreshold, the auto-mode overlap with hunkStagingOverlap, or turn the feature off with hunkStagingEnabled.
For the exact boundary rules and the engineering behind the navigation fix, see How Better Git VS Code navigation works.
Source Control show/hide automation is experimental and off by default
VS Code saves Source Control tree data per workspace, but current releases can still rebuild repository and change-group sections expanded after a restart. VS Code exposes no reliable extension API for reading or setting one particular repository or group node. Better Git's earlier attempt to reconstruct that mixed state by walking generic list rows became visibly repetitive with many worktrees, so v1.2.31 withdraws that implementation.
- Default: pure VS Code behavior. Better Git does not read Source Control tree storage, start a discovery timer, reveal or focus Source Control, select or walk rows, or expand/collapse anything during startup.
- Experimental automatic-behavior switch:
better-git-vscode.experimentalScmTreeStateManagement is off by default. Turning it on permits the optional startup behavior below, but does not itself perform any startup action.
- Manual button and command: click Better Git's Collapse All button (
$(collapse-all)) beside the AI sparkle in a Git repository's Source Control header, or run Better Git: Collapse all worktree / repository sections in Source Control (better-git-vscode.collapse-worktrees) from the Command Palette. Both invoke VS Code's built-in all-repositories collapse once and do not require either automatic setting.
- Optional startup collapse: also turn on
better-git-vscode.collapseWorktreesOnStartup to run that same built-in collapse once after 2+ repositories finish discovery. There are no retries and no row traversal.
Exact mixed-state restoration remains paused until VS Code provides a dependable per-node contract that can be tested without selecting rows or accidentally targeting another Source Control list such as Source Control Graph.
Reviewing a file that lives in another git worktree and want it in your workspace? Run Better Git: Add current file's git worktree to workspace (better-git-vscode.add-current-worktree-to-workspace) from the Command Palette. It finds the worktree the current (or under-review) file belongs to and adds that worktree's root as a workspace folder, so it shows up in your Explorer / Source Control sidebar.
The Open & Reveal File in Explorer command (better-git-vscode.reveal-current-file-in-explorer, Option+R by default) now does this automatically when needed. If the current diff/file belongs to a worktree that Source Control knows about but Explorer does not contain, one press opens the real editable file, adds that worktree root, waits for Explorer to register it, and reveals the file there. The explicit add-worktree command remains useful when you want to add the root without switching away from the diff. Turn off Auto-add worktree on reveal (better-git-vscode.autoAddWorktreeOnReveal) if you prefer reveal to open the file without changing workspace folders; it is on by default.
- Works from a diff, a plain editor, or while focus is in the Source Control panel — it uses the same "file under review" detection as the navigation commands.
- If the file isn't inside any git repository, it just tells you so (no error). If the worktree is already a workspace folder, it says so and does nothing.
- Note: if your window currently has a single folder open, adding the first extra folder turns it into a multi-root workspace, which triggers a quick window reload (VS Code restarts the extension host on that transition). Better Git VS Code warns you; the explicit add command performs the add as its very last step, while reveal opens the editable file first so it survives the restart and auto-reveals afterward.
Useful right-click actions
- Right-click a local
index.html in Explorer and choose Open index.html in System Browser, or use the same action on a changed index.html row in Source Control, to open that exact report/page in your default browser. VS Code does not expose filenames to SCM menu when clauses, so the Source Control action is visible on other Git rows too; its runtime guard refuses anything except a local index.html.
- Right-click any changed Source Control file and choose Open & Reveal File in Explorer to add its worktree when needed and reveal that exact row, even when another editor was active.
- Right-click a linked worktree header and choose Add Worktree to Workspace to append it to the current Explorer without replacing your existing workspace folders. Copy Worktree Name remains immediately above it.
Keybindings
The headline navigation keys are Alt+. and Alt+,. On a standard QWERTY keyboard
those are the physical > and < keys — "next" and "previous" feel obvious because
the keycaps literally point forward and back.
All bindings ship as defaults and are fully overridable (see below).
| Action |
macOS |
Windows / Linux |
| Next change |
Alt+. |
Alt+. |
| Previous change |
Alt+, |
Alt+, |
| Next changed file |
Cmd+Alt+. |
Ctrl+Alt+. |
| Previous changed file |
Cmd+Alt+, |
Ctrl+Alt+, |
| Stage current file + next change |
Shift+Alt+. |
Shift+Alt+. |
| Stage current file + previous change |
Shift+Alt+, |
Shift+Alt+, |
| Revert selected change and save |
Alt+Q* |
Alt+Q* |
| Reveal current file in Explorer |
Alt+R |
Alt+R |
| Open changes at cursor/scroll + Source Control |
Ctrl+Shift+G |
Ctrl+Shift+G |
Next / previous change walks hunk-to-hunk through the current diff, pages through
brand-new files a few lines at a time, and rolls over to the next/previous changed file
at either end. It's the one pair of keys you need for most reviews. (Before v1.2.5 these
keys pointed at the smart forward/back mouse commands, whose in-diff direction is
deliberately reversed for mouse thumb-buttons — which made keyboard > / < navigate
backwards on QWERTY. Fixed: they now run the real change-navigation commands.)
Smart forward / back (better-git-vscode.smart-forward / .smart-back) are
mouse-button commands with no default keyboard key: in a diff they go to the
previous/next change (direction intentionally reversed for thumb-buttons), elsewhere
they do normal editor back/forward. Bind them to your mouse's Forward/Back buttons
(e.g. via Karabiner → F13/F17 → keybindings.json).
Ctrl+Shift+G is remapped from VS Code's stock "show Source Control" chord (which only
opened the panel) to also open the current file's changes (diff) at the exact cursor and
scroll position you were viewing first, then show Source Control. Override it like any other
binding if you want the original behaviour back.
The + button in the editor title bar now stages the current file and advances to the
next change — in whatever direction you last navigated. Jump forward through changes (> / Alt+.)
and the + advances forward; jump backward (< / Alt+,) and it advances backward. So you can run
the whole review-and-stage flow with the mouse alone — click + to stage-and-jump instead of
clicking + then reaching for the keyboard. It calls the exact same logic as the Shift+Alt+. /
Shift+Alt+, keyboard shortcuts (same staging, same advance target, same cross-file rollover). A
fresh session with no navigation yet defaults to advancing forward. The plain, no-advance
Stage current file command is still registered if you'd rather bind that to a key.
Mouse-driven review (recommended setup)
You can drive the entire review-and-stage flow from your mouse — no keyboard at all. The trick
is a two-hop mapping: Karabiner-Elements remaps your mouse's extra buttons to spare F-keys, and
then VS Code's keybindings.json maps those F-keys to this extension's commands. This is the exact
setup the author uses.
The four commands you bind:
| Mouse button |
→ F-key |
→ Command |
What it does |
| Back (thumb rear) |
F13 |
better-git-vscode.smart-back |
In a review view: next change. Elsewhere: browser Back. |
| Forward (thumb front) |
F17 |
better-git-vscode.smart-forward |
In a review view: previous change. Elsewhere: browser Forward. |
| (extra button) |
F18 |
better-git-vscode.stage-and-next-changed-file |
Stage current file + next change. |
| (extra button) |
F19 |
better-git-vscode.stage-and-previous-changed-file |
Stage current file + previous change. |
Why the "smart" commands are dual-mode. smart-back / smart-forward detect whether you're in a
diff/review view (a diff, a brand-new/untracked file, a deleted file, a merge-conflict editor, or a
binary/image change). In a review view they navigate changes; anywhere else they behave as ordinary
editor Back/Forward — so the same physical thumb buttons keep their normal browsing meaning when
you're not reviewing, and become change-navigation the moment you're looking at a diff. (The in-diff
direction is intentionally flipped for thumb buttons — Back goes to the next change, Forward to
the previous — because that's what feels natural pressing them; see the note below.)
Everything behaves identically to the keyboard, because the mouse buttons call the exact same
functions the keyboard shortcuts do — no separate mouse code path. That means you get, for free:
the end-of-list guards (roll over to the next/previous changed file at either end, and don't strand
you on the last file), the few-lines-at-a-time scroll through brand-new files, and the tall-hunk
staged stepping. The editor-title-bar + button also stages-and-advances in your last-navigated
direction, so a click there is the mouse equivalent of F18/F19.
In Karabiner-Elements → Devices (or a Complex Modification), send F13, F17, F18, F19
from your mouse's buttons. F13 and F16–F19 have no default macOS action, so they pass straight through
to VS Code.
Avoid F14 / F15. On macOS those are the brightness down / up keys — the OS swallows them
before VS Code ever sees them, so a binding on F14 silently does nothing. Stick to F13 and
F16–F19.
2. VS Code: map the F-keys to the commands
Add these to your keybindings.json (Preferences: Open Keyboard Shortcuts (JSON)). They're
unconditional — the diff-vs-not decision is baked into the smart commands, so there's no when
clause to get wrong:
[
// Mouse BACK button (Karabiner sends F13) -> smart-back: next change while reviewing, else browser Back
{ "key": "f13", "command": "better-git-vscode.smart-back" },
// Mouse FORWARD button (Karabiner sends F17) -> smart-forward: previous change while reviewing, else Forward
{ "key": "f17", "command": "better-git-vscode.smart-forward" },
// Extra mouse buttons (Karabiner sends F18 / F19) -> stage-and-advance in each direction
{ "key": "f18", "command": "better-git-vscode.stage-and-next-changed-file" },
{ "key": "f19", "command": "better-git-vscode.stage-and-previous-changed-file" }
]
That's it — thumb-Back/Forward to fly through changes, the two extra buttons (or the title-bar +)
to stage-and-advance, all without touching the keyboard.
Left/right-hand navigation and Dvorak mode
By default, change navigation is available from both the right-hand physical > and < keys
and the left-hand physical Z and X keys. Set
better-git-vscode.navigationHands to left or right to keep only one pair active:
| Action |
Right-hand pair |
Left-hand pair |
| Next change |
Alt+. (physical >) |
Alt+X (physical X) |
| Previous change |
Alt+, (physical <) |
Alt+Z (physical Z) |
| Stage + next |
Shift+Alt+. |
Shift+Alt+X |
| Stage + previous |
Shift+Alt+, |
Shift+Alt+Z |
both is the default, so either hand works immediately. On QWERTY this intentionally
claims VS Code's built-in Alt+Z Toggle Word Wrap binding. Choose right if you want
only the established > / < pair and want VS Code's Alt+Z word-wrap shortcut back.
On Dvorak, also enable better-git-vscode.dvorakMode (Settings → Better Git
VS Code, or add it to settings.json) so both pairs stay on the same physical keys. VS Code
deliberately dispatches the macOS Dvorak – QWERTY Cmd layout by character key code, so
the extension contributes the characters that those physical keys actually produce:
This is a static VS Code setting, not automatic input-source detection. Turn it back off when
switching macOS to QWERTY or British so those layouts' Option+Z / Option+X and
Option+< / Option+> bindings become active.
| Physical pair |
QWERTY Next / Previous |
Dvorak Next / Previous |
Right (> / <) |
Alt+. / Alt+, |
Alt+V / Alt+W |
Left (Z / X) |
Alt+X / Alt+Z |
Alt+Q / Alt+; |
Shift adds Stage-and-Advance to the same pair in either layout. These settings use VS
Code's native configuration when-clauses, so changing either one swaps the active bindings
without an extension restart. Neither setting changes what the commands do.
The physical tilde/backtick key cannot be a reliable macOS Option shortcut inside text editors:
Option+backtick starts the system grave-accent dead-key composition, and VS Code receives
KeyInComposition instead of the physical key. Physical X is an ordinary non-composing key and
keeps the pair together under one hand.
Changed-file nav (Cmd/Ctrl+Alt+. / ,) and reveal (Alt+R) stay on their defaults.
On Dvorak, physical X produces Q, so enabling the left pair makes Alt+Q Next Change
and disables the conflicting Revert-and-Save default; choose navigationHands: "right" to
keep Revert on Alt+Q, or assign Revert another shortcut. This is the * exception in the
main shortcut table above. In Dvorak mode the freed-up Alt+. / Alt+,
characters additionally map to the smart forward/back mouse commands (they sit on
different physical keys there, so nothing collides).
Your own keybindings.json entries always win, so you can still hand-tune any of these
on top of the toggle (see Overriding any keybinding below).
Overriding any keybinding
Every default ships from the extension and can be overridden per command. To change one,
open Preferences: Open Keyboard Shortcuts, search for the command (they're all under the
better-git-vscode.* namespace — e.g. better-git-vscode.smart-forward), and assign your
own key. To disable a default instead, add a rule prefixed with - in keybindings.json:
{ "key": "alt+.", "command": "-better-git-vscode.next-scm-change" }
Tip: many people prefer to map Open & Reveal File in Explorer
(better-git-vscode.reveal-current-file-in-explorer) to something like Shift+Cmd+E.
We ship the default as Option+R rather than Shift+Cmd+E because the latter is already
a built-in VS Code shortcut — but you're free to override it to Shift+Cmd+E (or anything
else) in your own keybindings.json if you don't mind reclaiming that combo. Bind the Better Git
command unconditionally; isInDiffEditor becomes false while Source Control owns keyboard focus even if a
diff remains visibly active, which would otherwise send the key to VS Code's built-in non-worktree-aware reveal.
Settings
A few behaviours are configurable under Settings → Better Git VS Code:
- Navigation hands — choose the right-hand physical
> / < pair, the left-hand physical Z / X pair, or both (better-git-vscode.navigationHands, default both). On QWERTY, choose right to preserve VS Code's built-in Alt+Z Toggle Word Wrap shortcut. On Dvorak, choose right to preserve Better Git's Alt+Q Revert-and-Save shortcut.
- Dvorak mode — remap both navigation pairs to the characters produced by the same physical keys under Dvorak (
better-git-vscode.dvorakMode, see the section above).
- Last-staged status bar — a bottom-left
✓ Staged: <filename> indicator showing the last file you staged through the extension, so a fast stage-and-advance never stages something without you noticing. Click it to reopen that file's staged diff and unstage it if it was a mistake. Toggle with better-git-vscode.showLastStagedInStatusBar (default on).
- Experimental Source Control automation — automatic tree manipulation is off by default behind
better-git-vscode.experimentalScmTreeStateManagement. The manual Command Palette collapse remains available; the separate collapseWorktreesOnStartup double opt-in runs one built-in collapse with no retries. Exact mixed-state restoration is paused. See Source Control show/hide automation is experimental and off by default above.
- Auto-add worktree on reveal — when reveal targets a worktree outside Explorer, add that worktree root as a workspace folder and reveal the file (
better-git-vscode.autoAddWorktreeOnReveal, on by default; see Pull a worktree into your sidebar above).
- Commit-message AI provider — the first use detects Codex and Claude Code, asks which signed-in account to use, and remembers that choice inside Better Git. Use Better Git: Change Commit Message AI Provider to switch later.
- AI executable paths — configure the signed-in Codex CLI (
better-git-vscode.codexExecutablePath, default codex) or Claude Code CLI (better-git-vscode.claudeExecutablePath, default claude) if VS Code cannot resolve it.
- New-file line step — how many lines the change keys step through a brand-new file (
better-git-vscode.newFileNavLineJump, default 5).
- Tall-hunk staging — present or step through any hunk whose complete rendered range is not on-screen, instead of letting unread lines run off the bottom (
better-git-vscode.hunkStagingEnabled, default on — see Step through tall hunks in stages above). Tune the engage threshold (hunkStagingThreshold, 0 = auto/rendered visibility), the exact per-step move (hunkStagingLineStep, default 10; any positive custom value; 0 = viewport-minus-overlap auto mode), and the overlap used by auto mode (hunkStagingOverlap, default 4).
- List vs Tree view in Source Control (
better-git-vscode.treeView).
- Whether the Source Control panel opens on navigation (
shouldOpenScmView).
- The badge shown on the file you're currently reviewing (
currentFileBadge, default 🔥🔥).
- Experimental staged-file highlighting (
revealStagedInSourceControl).
Credits
Better Git VS Code is a fork of the original git-diff-navigation extension by
Alfred Birk, extended with a stage-and-advance
review flow, staged-diff navigation, smart forward/back, and the QWERTY < / >
default keys. Thanks to Alfred Birk for the original extension.
License
MIT.