CVS Source Control
VS Code extension that integrates CVS as a native Source Control provider — the same look and feel as the built-in Git extension.
Key features
Git-style SCM panel with staging
Files are split into Staged Changes, Changes, Untracked Files, Conflicts, ↓ Incoming Changes, and ⚠ Incoming Conflicts groups — identical in structure to the Git panel. CVS has no native staging; the extension emulates it by recording staged filenames locally and passing them explicitly to cvs commit. Full per-file context menu in each group, with group header buttons on every group: Stage All on Changes, Unstage All on Staged Changes, Update All on Incoming Changes, Add All on Untracked Files (each file added by its own detected text/binary type), and Revert All on Conflicts (confirms first).
Incoming changes
The SCM panel is populated on open with a full dry-run sync, so ↓ Incoming Changes and ⚠ Incoming Conflicts include server-side new files and directories without a manual check. Check Remote runs the same sync on demand with forced directory relisting. Results appear in ↓ Incoming Changes (safe to pull) and ⚠ Incoming Conflicts (server changed, local also modified). Incoming new directories are expanded into file rows when their server listing is small enough; use View as Tree from the SCM view's ... menu to see those rows as a hierarchy. Safe Pull pulls only the safe files in one batch. Set an auto-check interval (clock button) to poll the server automatically.
Conflict resolution
⚠ Incoming Conflicts shows files where merging would be risky. Click one to open VS Code's 3-way merge editor with your local edit as "Current" and the server revision as "Incoming". After saving, CVS: Resolve Incoming Conflict advances the file to the server revision and marks it M — ready to commit. CVS conflict-marker files (after a failed cvs update) open the same editor using the .# backup CVS left behind.
Diffs
Click any file in Changes or ↓ Incoming Changes for a side-by-side diff — no server round-trip for local changes (revision pinned from CVS/Entries). QuickDiff gutter bars appear on modified lines in the editor. Conflict marker lines (<<<<<<<, =======, >>>>>>>) are highlighted in red.
Commit history
CVS: Show History (SCM title or Explorer right-click) opens a filterable history panel. Commits by the same author with the same message within a configurable time window are grouped into one changeset row. File-targeted view shows one row per revision and a Compare button for side-by-side diffs of any two revisions.
Session log
The CVS Session Log panel in the SCM sidebar tracks every operation of the current session (commits, updates, reverts, pulls) with affected files and revision ranges. Filters to the active file automatically. Entries also appear in VS Code's built-in Timeline panel.
Explorer integration
Right-click any file or folder in a CVS working copy and choose CVS for the same operations available in the SCM panel — Update, Commit, Add / Add Binary, Stage / Unstage, Remove, Revert, Rename, Tag, Ignore, Show History, Annotate, Diff, Resolve Conflict, plus folder-level Release and Checkout Subfolders. Menu entries only appear when applicable to the selected item's actual state (e.g. Add only for untracked files, Commit/Revert only for files with local changes) instead of showing every command unconditionally.
CVS commands covered
| Command |
Notes |
update |
full repo, per-file, dry-run (Check Remote) |
commit |
all changes or staged subset |
add |
|
remove |
|
tag |
commit-time, retrospective per-revision, or standalone on any file/folder |
diff |
local vs base, local vs previous revision, incoming vs local, any two revisions |
log / rlog |
history panel with changeset grouping |
annotate |
|
status |
SCM panel and auto-refresh |
Planned
| Feature |
|
branch |
update-to-branch, merge-from-branch |
login |
authenticate from within VS Code on auth failure |
| Multi-select |
batch operations across selected files in SCM and Explorer |
Settings
| Setting |
Default |
Description |
cvs.cvsRoot |
"" |
Fallback CVSROOT if CVS/Root is absent |
cvs.folders |
[] |
Additional CVS checkout directories to activate, beyond workspace folder roots (absolute paths) |
cvs.showUntrackedFiles |
true |
Show untracked files in the SCM panel |
cvs.showBothAddCommands |
false |
Show both Add and Add Binary regardless of detected file type |
cvs.fileWatchCooldown |
1 |
Seconds between file-watcher-triggered refreshes; 0 disables |
cvs.incoming.maxExpandedDirFiles |
200 |
Maximum server files to expand from an incoming new directory into SCM rows; 0 keeps incoming directories as single browseable rows |
cvs.incoming.maxParallelListings |
8 |
Maximum incoming directory listing commands to run in parallel after the first remote-check paint |
cvs.incoming.listingProgressThreshold |
3 |
Minimum incoming directory listing batch size that shows cancellable notification progress |
cvs.verboseOutput |
false |
Log CVS command output to the Output channel |
cvs.warnOnCommitAll |
true |
Warn before committing with nothing staged |
cvs.logGroupingWindowSeconds |
120 |
Max seconds between revisions to group as one changeset |
cvs.logMaxEntries |
100 |
Max changesets shown in the History panel |
cvs.historyDateFormat |
"YYYY-MM-DD HH:mm" |
Date format in the History panel |
Requirements
- VS Code 1.85+ — desktop, Remote SSH, Dev Containers, or Codespaces (not VS Code for the Web)
cvs on PATH
- CVSROOT auto-detected from
CVS/Root; fallback: cvs.cvsRoot setting
Tests
npm run test:behavior runs local CVS behavior coverage only. It does not exercise client/server pserver behavior.
To run the pserver behavior suite, provide a pserver root through the environment:
CVS_TEST_PSERVER_ROOT=':pserver:user@host:/path/to/cvsroot' npm run test:behavior:pserver
The pserver suite covers mode-sensitive CVS behavior such as incoming new-directory reporting, status -v keyword options for binary files, aborts for files in unchecked-out directories, rls -e -R listings, and selective fetches into directory shells. Running it without CVS_TEST_PSERVER_ROOT registers a visible skipped test instead of silently omitting pserver coverage.