JetBrains IDEA–style changelists for VSCode. Group your working-tree changes into named changelists and commit only the ones you choose. Files in the default ("Changes") changelist get committed; files you move into another changelist are held back.
How it works
Git has no native concept of changelists — JetBrains implements them entirely in its UI, and so does this extension. All your modified files stay in the working tree. A changelist is just a local grouping remembered per-workspace. When you commit a changelist, the extension stages exactly that changelist's files (unstaging everything else first) and commits them. Other changelists are never touched.
State is stored in <repo>/.git/changelists.json — local to your machine, never
committed (nothing under .git/ ever is), and independent of the extension's own
storage. This means changelists survive extension updates, reinstalls, and even
"delete extension data" prompts, the same way JetBrains keeps changelist
membership in .idea/workspace.xml rather than IDE state. Upgrading from a
version before 0.0.9 migrates your existing assignments automatically on first
load.
Multi-root workspaces
If your workspace has more than one folder with a git repo, the view shows one
top-level node per folder, each with its own Changes, custom changelists,
and Unversioned Files underneath — completely independent changelist state
per repo (each persists to its own <repo>/.git/changelists.json). With a
single repo open, the view stays flat exactly as before — no redundant
top-level wrapper.
Removing a folder from the workspace removes its node from the view
immediately (its changelists.json is untouched on disk, so re-adding the
folder later restores its changelists exactly as they were).
Because Pull/Push/New Changelist/Update from Branch need to know which repo to act on, they move off the view's title bar and onto each folder's own row (inline icons + right-click) once there's more than one repo. With a single repo they stay on the title bar as usual.
Usage
-
Use the Pull / Push buttons in the view title bar to sync with the remote. Pushing a branch with no upstream yet prompts you to pick a remote and sets it up automatically.
- Push opens a preview window first — it lists exactly which commits
will be sent, to which destination (
remote/branch), before anything leaves your machine. Nothing is pushed until you click Push in that window. It warns if your branch is behind the remote (push may be rejected), and for a brand-new branch shows the commits that branch adds on top of the remote'smain/master. - Pull always fetches, then explicitly merges or rebases onto your
upstream — it never runs plain
git pull, so it never hits git's "you have divergent branches, please reconcile" prompt. Which one it uses is thechangelists.pullStrategysetting (mergeby default), equivalent to JetBrains' "Update Method". Change it in Settings if you prefer rebase. - Working on a feature branch and want to catch up with
main? Use the...menu → Update from Branch... — pick the branch (local or remote, e.g.origin/main), then Merge or Rebase. It fetches the latest first, so you always update against the remote's current state, not a stale local copy. On conflicts, resolve them in the Source Control view as usual, then continue (rebase) or commit (merge).
- Push opens a preview window first — it lists exactly which commits
will be sent, to which destination (
-
Open the Changelists view in the activity bar (list-tree icon).
-
All current changes appear under the active changelist (default:
Changes). -
New Changelist (
+in the view title) to create one. -
Move files between changelists either by:
- Drag and drop — select one or more files (Cmd/Ctrl- or Shift-click for multi-select) and drag them onto a changelist; or
- Right-click a file → Move to Changelist….
Dragging an untracked file out of Unversioned Files onto a changelist adds it to version control first (
git add -N), same as right-click → Add to Changelist…. Conversely, dragging a newly-added file (statusA, not yet committed) onto Unversioned Files unstages it back to untracked (statusU). Files with real commit history (modified, renamed, deleted) can't be moved to Unversioned Files this way — there's no way to make a file with history "untracked" without rewriting history, so those drops are rejected with an explanation. -
Right-click a changelist → Commit Changelist… (or use the inline check-all icon, or the Commit button in the view title bar) to open the commit dialog: a checkable file list (uncheck to leave a file out of this commit), a multi-line commit message, an Amend previous commit option, and click-to-diff on any file. ⌘/Ctrl+Enter commits.
- Right-click a changelist → Show Diff (or the inline multi-diff icon) to open every changed file in that changelist at once, in VSCode's multi-file changes editor — the same view used for reviewing a commit.
- Want to commit just one file, or a handful, without touching the rest of the changelist? Select the file(s) (Cmd/Ctrl- or Shift-click for multi-select) → right-click → Commit Selected... — opens the same commit dialog, scoped to just what you selected.
-
Right-click a changelist → Set as Active to make new changes land there.
-
Git Graph — open a visual commit graph (all branches, colored lanes, branch/tag/HEAD labels) from the view title bar (single repo) or a folder row (multi-repo). Click any commit to open its changed files, each diffed against the commit's parent. Use the branch dropdown to scope the graph to one branch, and the search box to filter/highlight commits by hash or words in the commit message.
-
Show File History — right-click a file (in the editor, the Explorer, or a Changelists-view row) to open the same graph filtered to that file — every commit that touched it, across branches. Click a commit to see what it did to that file (diffed against its parent). Note: history follows the current path only (renames are not followed).
Notes / limitations (MVP)
- Move/commit work at file granularity (no partial/hunk staging per changelist).
- Assignments are pruned automatically when a file no longer has changes.
- Dragging a file onto a changelist in a different repo is rejected — a file can only belong to a changelist in its own repository.