Render diffs for committed changes, not just uncommitted ones - #60
Merged
phine-apps merged 1 commit intoJul 23, 2026
Merged
Conversation
Opening a committed Markdown file's diff - selecting a commit in the
Source Control Graph and clicking one of its changed .md files - showed
"No Markdown changes are available for this file" even though the diff
button appeared in the editor title bar. Reviewing a document change
after the fact is exactly when a rendered diff is most useful, so this
was the one case where the extension could not help.
The refs identifying each side were being discarded before any
comparison was resolved:
- `toFileBackedUri` rewrites a `git:` URI to its `file:` path, dropping
`query.ref`. `getCommandTarget`'s `vscode.Uri` branch applied that
rewrite and hardcoded a hint of "auto", so a commit SHA never survived
argument parsing.
- `getComparisonHintFromUris` only recognized the index (""), the working
tree ("~"), and HEAD; `GitComparisonHint` had no value able to carry a
commit at all.
- `showDiff` never read the `originalUri`/`modifiedUri` that
`getCommandTarget` already returns, so both sides were available and
then thrown away.
The comparison therefore fell back to HEAD versus working tree, which for
a clean file resolves to `cleanHeadToWorkingTree` and is rejected as not
actionable - the message the user saw.
Changes:
- Add `isRevisionRef` to tell a commit, tag, or branch ref apart from the
three well-known refs the existing modes already express, plus
`shortenRef` and `describeComparisonSide` to label each side.
- Add `getRevisionComparison` to detect a comparison naming a revision,
and `getActiveDiffTabUriPair` to recover the counterpart revision from
the focused diff tab, since the editor title bar passes only the active
resource.
- Route such comparisons in `showDiff` to a new `showRevisionDiff`, which
renders the two revisions directly. Content already resolves through
the Git extension's content provider, so only the routing was missing.
- Guard the tab fallback with `refersToSameFile` so an unrelated diff tab
cannot hijack a command aimed at another file.
- Export `normalizeFsPath` and reuse it rather than duplicating path
normalization, and use the new ref constants in
`getComparisonHintFromUris`.
This also fixes the quieter half of the bug: when the file had
uncommitted edits the command previously showed the working-tree diff
instead of the commit diff that was clicked.
Fixes phine-apps#59
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
phine-apps
pushed a commit
that referenced
this pull request
Jul 24, 2026
After #60 the title-bar button renders a committed revision diff, but right-clicking inside that diff editor still did not offer "Show Rich Markdown Diff" — the button uses the built-in `isInDiffEditor` context, while the context menu is gated on `rich-markdown-diff.canShowRenderedDiff`, and the two disagreed. The context key is computed by `updateRenderedDiffContext`, which — like the original #59 bug — rebuilds the active editor's `git:` URI as a plain `file:` URI, dropping the commit ref. The comparison then resolves as HEAD-vs-working-tree, a committed blob is not dirty, and `isActionableSingleFileComparison` returns false, so the key stayed off. - Add `getActiveRevisionComparison`, reusing #60's `getActiveDiffTabUriPair` and `getRevisionComparison`, to report the revision diff the active tab is showing. - In `updateRenderedDiffContext`, short-circuit to canShow = true when the active tab is a markdown revision diff, before the ref-dropping fallback runs. The markdown-path check stops a non-markdown diff in another editor group from enabling the key. - Factor the repeated "set the context key only if it changed, and only if this update has not been superseded" logic into `setCanShowRenderedDiff`, and use it at the existing call sites. Fixes #61 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
phine-apps
added a commit
that referenced
this pull request
Jul 24, 2026
…diff Hi @wolframarnold! Awesome job again! Thank you so much for following up on your previous PR (#60) with this one. Adding support to trigger the Rendered Diff from the editor context menu makes the workflow smoother when digging through commit history. I also really appreciate the clean implementation of the asynchronous generation guard—that's a very smart way to prevent race conditions. I've run the test suite and everything looks pristine. Merging this right away. Thank you for your continued support and for making this project so much better!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #59.
Opening a committed Markdown file's diff — selecting a commit in the Source Control Graph and clicking one of its changed
.mdfiles — showedNo Markdown changes are available for this file, even though the diff button appeared in the editor title bar.Why it happened
The refs identifying each side were discarded before any comparison was resolved:
commandTarget.tstoFileBackedUrigit:URI to itsfile:path, droppingquery.ref. Thevscode.Uribranch ofgetCommandTargetapplied that rewrite and hardcodedcomparisonHint: "auto", so a commit SHA never survived argument parsing.gitDiffResolver.tsgetComparisonHintFromUris""(index),"~"(working tree), andHEAD.GitComparisonHinthad no value able to carry a commit at all.extension.tsshowDifforiginalUri/modifiedUrithatgetCommandTargetalready returns — both sides were available and then thrown away.The comparison fell back to HEAD vs working tree, which for a clean file resolves to
cleanHeadToWorkingTreeand is rejected byisActionableSingleFileComparison— the message the user saw.What changed
Deliberately additive: no existing comparison path changes behavior. A comparison is routed to the new code only when a side names a ref that is not
"","~", orHEAD.isRevisionRefdistinguishes a commit / tag / branch ref from the three well-known refs the existing modes already express.shortenRefanddescribeComparisonSidebuild the labels.getRevisionComparisondetects a comparison naming a revision.getActiveDiffTabUriPairrecovers the counterpart revision from the focused diff tab viaTabInputTextDiff, because the editor title bar passes only the active resource.showRevisionDiffrenders the two revisions directly. Content already resolves through the Git extension's content provider (openTextDocumenton agit:URI), so only the routing was missing.refersToSameFileguards the tab fallback so an unrelated diff tab cannot hijack a command aimed at another file.normalizeFsPathis exported and reused instead of duplicating path normalization, andgetComparisonHintFromUrisnow uses the new ref constants instead of bare""/"~"literals.Panel titles read
Markdown Diff: example.md (086bdd7 ↔ 010c6f6). Full 40-character SHAs are shortened to 7; branch and tag names are shown as-is. Since both sides of a commit diff share a basename, the existing basename labeling would have produced two identical labels.This also fixes the quieter half of the bug: when the file had uncommitted edits, the command previously showed the working-tree diff instead of the commit diff that was clicked.
Tests
15 new integration tests in
commandTarget.test.tsandgitDiffResolver.test.ts, written before the implementation. Suite goes 22 → 47 passing;test:unitstays at 150.pnpm run pretestis clean.Coverage: ref classification (commit / tag / branch /
HEAD/ index / working tree / absent), SHA shortening, side labeling, revision-pair detection including every negative case, same-file matching, and reading both sides of a real diff editor opened withvscode.diff.Separately, I verified the fix end-to-end against a scratch git repository with two commits: both revisions read correctly through the git content provider, and the command produced a panel titled
Markdown Diff: example.md (086bdd7 ↔ 010c6f6). With the source changes reverted and that same check kept, no panel is created at all — confirming it reproduces the reported bug. That check is not included here because the test harness does not open a workspace folder, and adding one torunTest.tsfelt out of scope for a bug fix.Notes for review
multiDiffEditorOriginalUri/multiFileDiffEditorModifiedUri, whichextractComparisonUrisalready collects — so those land on the argument path rather than the tab fallback. Both are handled.canShowRenderedDiffis left as is, and it is still inconsistent. Theeditor/titlemenu shows the button viaisInDiffEditor, while the context key staysfalsefor a clean committed file. The title-bar button now works, but the right-click editor context menu still will not offer the command there, because itswhenclause requires the context key. Fixing that means teachingupdateCanShowRenderedDiffContextabout revision comparisons too — happy to add it here or in a follow-up, whichever you prefer.package.nls.*and thel10nbundles are untouched.