Skip to content

feat(cli): compare two revisions explicitly - #938

Merged
benvinegar merged 2 commits into
mainfrom
feat/two-commit-diff
Aug 31, 2026
Merged

benvinegar merged 2 commits into
mainfrom
feat/two-commit-diff

Conversation

@benvinegar

@benvinegar benvinegar commented Aug 30, 2026

Copy link
Copy Markdown
Member

Summary

  • make hunk diff <from> <to> compare two revisions deterministically
  • keep revision endpoints structured until Git, Jujutsu, or Sapling formats its native command
  • move concrete file comparison to the explicit hunk diff --files <left> <right> form
  • preserve pinned source expansion, read-only historical review policy, session reloads, watch mode, and working-copy isolation
  • expose structured rangeEndpoints through extension API generation 14

This rebuilds and supersedes #678 on current main, retaining the original contribution's intent and credit to @HackAttack while integrating with the current VCS extension, session protocol, and workspace safety boundaries.

Behavior

Command Meaning
hunk diff working-tree review, including untracked files by default
hunk diff A backend-native target/range review
hunk diff A B historical comparison from revision A to revision B
hunk diff A B -- path historical comparison restricted to a pathspec
hunk diff --files before.ts after.ts concrete two-file comparison

Two-revision comparisons exclude unrelated working-copy and untracked files. Git uses A..B, Jujutsu uses --from A --to B, and Sapling uses two -r arguments. Each endpoint is validated independently before backend probes or commands.

Before and after by VCS

Git

Intent Before After
Working tree hunk diff hunk diff
Working tree vs target hunk diff maingit diff main unchanged
Git range expression hunk diff main..feature unchanged
Two separate revisions hunk diff main feature treated feature as a pathspec hunk diff main featuregit diff main..feature
Two revisions with a path filter no direct two-endpoint form hunk diff main feature -- src/
Two concrete files hunk diff before.ts after.ts, guessed from filesystem state hunk diff --files before.ts after.ts, deterministic

Jujutsu

Intent Before After
Working copy hunk diff unchanged
One revset hunk diff '@-'jj diff -r @- unchanged
Two separate revisions hunk diff A B treated B as a fileset hunk diff A Bjj diff --from A --to B
Two-tree comparison no structured form; A..B is a revset rather than two tree endpoints backend-native --from A --to B
Two revisions with a fileset no direct two-endpoint form hunk diff A B -- src/
Watched @ endpoint not representable as two endpoints hunk diff A @ --watch snapshots and refreshes working-copy changes

Sapling

Intent Before After
Working copy hunk diff unchanged
Working copy vs target hunk diff mainsl diff -r main unchanged, including unknown-file behavior
Backend revset expression hunk diff REVSET unchanged
Two separate revisions hunk diff A B treated B as a path hunk diff A Bsl diff -r A -r B
Two revisions with a path filter no direct two-endpoint form hunk diff A B -- src/
Historical working-copy isolation no direct two-endpoint form endpoint comparisons exclude current unknown files

Verification

Automated:

  • bun run typecheck
  • bun run lint
  • bun run deps:check
  • bun run check:docs
  • bun run test — 2,127 passed, 3 Sapling-dependent tests skipped
  • bun run test:integration — 139 passed, 1 macOS-only test skipped

Real TTY testing in tmux at 120×36 on Linux:

  • Git historical comparison rendered changes from exactly A to B
  • Git historical comparison excluded current tracked edits and untracked files
  • bare Git working-tree review continued to include tracked and untracked changes
  • endpoint pathspecs excluded unrelated historical files
  • --files rendered a concrete file pair
  • existing filesystem names used positionally were treated as revisions, not guessed as files
  • option-shaped input failed closed without creating the requested output path
  • Jujutsu historical comparison excluded later working-copy changes
  • Jujutsu @ endpoint watch mode refreshed after an ordinary filesystem edit

Sapling is not installed on this machine, so executable-backed Sapling tests remain skipped; exact command construction, validation, untracked policy, and adapter-spawn behavior are covered by unit tests.

No visual styling changed, so screenshots are not included.

This PR description was generated by Pi using OpenAI Codex gpt-5.6-sol

@vercel

vercel Bot commented Aug 30, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
hunk-web Ready Ready Preview Aug 30, 2026 11:57pm

Request Review

@greptile-apps

greptile-apps Bot commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

Too many files changed for review (60 files, 50 file limit).

Bypass the limit by tagging @greptile-apps to review.

@benvinegar
benvinegar merged commit 598e084 into main Aug 31, 2026
12 checks passed
@benvinegar
benvinegar deleted the feat/two-commit-diff branch August 31, 2026 00:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant