Skip to content

fix: keep dirty committed files visible when hiding Committed - #254

Draft
Ziinc wants to merge 3 commits into
mainfrom
cursor/fix-committed-dirty-toggle-f233
Draft

fix: keep dirty committed files visible when hiding Committed#254
Ziinc wants to merge 3 commits into
mainfrom
cursor/fix-committed-dirty-toggle-f233

Conversation

@Ziinc

@Ziinc Ziinc commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

Summary

Hiding Review Committed via the Show toggle was removing every committed file, including paths that still have working-copy changes.

Fix

  • Backend: workspace_diff keeps overlapping paths in both committed_files and uncommitted_files (no longer strips dirty committed files).
  • Frontend: Show off only hides clean committed-only files. Dirty and conflicted committed paths stay in the sidebar and diff pane.

Tests

  • Rust: overlapping path present in both lists
  • Unit/integration: Show off keeps dirty committed rows, hides clean ones
  • Screenshot: review-committed-dirty-toggle

App QA

Show on — shared in Changes and Committed
Show off — committed-only hidden, shared stays
To show artifacts inline, enable in settings.

Open in Web Open in Cursor 

cursoragent and others added 3 commits August 11, 2026 13:09
The Review Committed Show toggle was hiding every committed file,
including paths that still have working-copy changes. Stop stripping
overlapping paths from workspace_diff, and only hide committed-only
files when Show is off.

Co-authored-by: Ziinc <Ziinc@users.noreply.github.com>
Co-authored-by: Ziinc <Ziinc@users.noreply.github.com>
Co-authored-by: Ziinc <Ziinc@users.noreply.github.com>
showCommittedChanges: boolean,
alwaysVisiblePaths: ReadonlySet<string>,
): boolean {
return showCommittedChanges || alwaysVisiblePaths.has(path);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shared Show-visibility rule used by the sidebar, diff pane, search, and hunk loader.

  • Show on → all committed files
  • Show off → only paths in the always-visible set (WC-dirty ∪ conflicted)
  • Permalink:
    export function shouldShowCommittedFile(
    path: string,
    showCommittedChanges: boolean,
    alwaysVisiblePaths: ReadonlySet<string>,
    ): boolean {
    return showCommittedChanges || alwaysVisiblePaths.has(path);
    }
    export function filterVisibleCommittedFiles<T extends { path: string }>(
    committedFiles: T[],
    showCommittedChanges: boolean,
    alwaysVisiblePaths: ReadonlySet<string>,
    ): T[] {
    if (showCommittedChanges) return committedFiles;
    return committedFiles.filter((file) =>
    shouldShowCommittedFile(file.path, false, alwaysVisiblePaths),
    );

.map_err(|e| format!("Failed to get workspace diff: {}", e))?;

// Keep overlapping paths in both lists. Review's Committed Show toggle hides
// clean committed-only files; dirty committed files must remain visible.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the committed_files.retain(...) that dropped paths also present in the WC.

  • Frontend Show already decides what to hide; backend dedupe made dirty committed files impossible to keep visible
  • Overlap is intentional: Review shows committed tip vs WC separately for the same path
  • Permalink:
    // Keep overlapping paths in both lists. Review's Committed Show toggle hides
    // clean committed-only files; dirty committed files must remain visible.
    let uncommitted_files = jj::jj_get_changed_files(workspace_dir_str)
    .map_err(|e| format!("Failed to get uncommitted workspace changes: {}", e))?;
    let conflicted_files = jj::get_conflicted_files(workspace_dir_str, Some(target_branch))
    .map_err(|e| format!("Failed to get conflicted workspace files: {}", e))?;
    diff.uncommitted_files = uncommitted_files;
    diff.conflicted_files = conflicted_files;

(fileDiff) =>
showCommittedChanges || conflictedHint.has(fileDiff.path),
showCommittedChanges ||
alwaysVisibleCommitted.has(fileDiff.path),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hunk map must match the visible committed rows when Show flips.

  • Previously only conflicted hunks survived hide; dirty overlapping hunks disappeared too
  • uncommittedPaths ∪ conflictedHint keeps the committed tip hunk for files still under active edit
  • Permalink:
    // When Committed is hidden, still keep dirty + conflicted committed hunks.
    const alwaysVisibleCommitted = new Set([
    ...uncommittedPaths,
    ...conflictedHint,
    ]);
    setCommittedFileHunks(
    new Map(
    (diff.hunks_by_file ?? [])
    .filter(
    (fileDiff) =>
    showCommittedChanges ||
    alwaysVisibleCommitted.has(fileDiff.path),

const showFiles = showCommittedChanges && !isCollapsed;
const visibleFiles = showCommittedChanges
? files
: files.filter((file) => alwaysVisiblePaths?.has(file.path));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sidebar list now filters instead of blanking the whole section when Show is off.

  • Header + count stay so the toggle remains reachable
  • Dirty/conflicted rows remain selectable while clean committed-only rows hide
  • Permalink:
    const visibleFiles = showCommittedChanges
    ? files
    : files.filter((file) => alwaysVisiblePaths?.has(file.path));
    const showFiles = !isCollapsed && visibleFiles.length > 0;

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.

2 participants