GitDiff
Diff your working tree against any branch or commit — and keep editing.
Why GitDiff?
VS Code's built-in Git diff compares against HEAD or the index. It does not let you ask:
"How does this file in my working tree look compared to origin/main? Or to that commit from last Tuesday?"
GitDiff does exactly that — and unlike a read-only git diff, the working-tree side stays live and editable. You can read the comparison and fix the code in the same view, then hit save.
Features
- Compare against any branch — local or remote-tracking, with a quick-pick search.
- Compare against any commit — recent commits in a picker, plus a free-form "Enter SHA…" option.
- Editable right pane — it's the real file on disk. Edit and save like any normal editor.
- Read-only left pane — backed by
git show <ref>:<path>, so you can't accidentally clobber history.
- Changed-Files sidebar — pick a target once, see every file in your tree that differs from it, click to open the diff.
- Live branch tracking — when comparing against a branch, "Refresh" re-resolves it to the current tip.
- Repo-aware — works correctly with multi-root workspaces, nested repos, and reserved characters in branch names.
- Safe by default — refuses to diff binary or non-UTF-8 blobs, declares no virtual-workspace support, and the
git binary path is machine-scoped (workspace settings can't override it).
Install
From the Marketplace
ext install tigercosmos.gitdiff
From a .vsix
code --install-extension gitdiff-0.1.0.vsix
Usage
Compare a single file
- Open any file from your workspace.
- Run one of:
GitDiff: Compare with Branch…
GitDiff: Compare with Commit…
- Pick a target. The diff opens with the target on the left (read-only) and your working-tree file on the right (editable).
You can also right-click a file in the Explorer or on the editor tab to launch either command.
Browse every changed file
- Click the GitDiff icon in the Activity Bar.
- Hit Set Comparison Target… in the view's title.
- Click any file in the tree to open its diff against your chosen target.
- Use the Clear Comparison Target button (
$(clear-all)) in the view's title to drop the target and close every open GitDiff diff in one click.
Editor title actions
When a GitDiff diff is the active editor:
| Action |
Command |
| Refresh the diff (re-resolves branch tips) |
gitdiff.refresh |
| Pick a different target |
gitdiff.changeTarget |
Commands
| Command |
ID |
| Compare with Branch… |
gitdiff.compareWithBranch |
| Compare with Commit… |
gitdiff.compareWithCommit |
| Refresh Diff |
gitdiff.refresh |
| Change Target… |
gitdiff.changeTarget |
| Set Comparison Target… (sidebar) |
gitdiff.changedFiles.setTarget |
| Refresh Changed Files (sidebar) |
gitdiff.changedFiles.refresh |
| Clear Comparison Target (sidebar) |
gitdiff.changedFiles.clearTarget |
Configuration
| Setting |
Type |
Default |
Description |
gitdiff.commitPickerLimit |
number |
100 |
Maximum number of recent commits shown in the commit picker (1–5000). |
gitdiff.gitPath |
string |
"" |
Absolute path to the git executable. Empty resolves from PATH. Machine-scoped — workspace settings cannot override it. |
Requirements
- VS Code 1.85 or newer.
- A local
git binary on PATH (or set gitdiff.gitPath).
- A real
file: workspace. Virtual workspaces (vscode.dev, browser-based Codespaces, Remote – Repositories) are not supported.
How it works
┌──────────────────────────────────────────────────────────────┐
│ extension.ts — activation, command + provider wiring │
├──────────────────────────────────────────────────────────────┤
│ GitService — shells out to `git` via execFile │
│ RefPicker — QuickPick UI for branches and commits │
│ DiffOpener — builds URIs and calls vscode.diff │
│ GitShowProvider — TextDocumentContentProvider (left) │
│ ChangedFilesProvider — TreeView for the sidebar │
│ ActiveDiffTracker — maintains the activeDiff context key │
└──────────────────────────────────────────────────────────────┘
The left pane is a virtual document with the gitdiff: scheme:
gitdiff:/<repo-relative-path>?ref=<full-sha>&repo=<absolute-repo-root>[&branch=<branch>]
The ref is pinned to a verified 40-char SHA at open time (so the left pane is reproducible), the repo root is encoded explicitly (so multi-root and nested-repo workspaces resolve correctly), and the file path stays in the URI's path (so language detection just works). When you compare against a branch, the original branch name is preserved in branch= so Refresh can re-resolve it to the current tip; diffs opened against a specific commit omit branch= and stay pinned. All three values round-trip through URLSearchParams, so /, ?, #, &, %, spaces, and non-ASCII characters survive intact. The right pane is the unmodified file: URI for the workspace file — that's why edit and save behave normally.
Development
npm install
npm run compile # tsc
npm run watch # incremental build
npm test # integration tests (VS Code test host)
npm run test:unit # unit tests (mocha + ts-node)
npm run package # build a .vsix
Press F5 in VS Code to launch an Extension Development Host with the extension loaded.
License
MIT