Skip to content

Git diff: commit history + diff-in-a-tab reshape (#117)#1534

Open
adradr wants to merge 44 commits into
getpaseo:mainfrom
adradr:feat/git-diff-tree-and-commits
Open

Git diff: commit history + diff-in-a-tab reshape (#117)#1534
adradr wants to merge 44 commits into
getpaseo:mainfrom
adradr:feat/git-diff-tree-and-commits

Conversation

@adradr

@adradr adradr commented Jun 14, 2026

Copy link
Copy Markdown

Adds commit history + a reshaped diff experience to the git Changes view, following the direction in the maintainer's reply (diff moves into a tab, sidebar stays listing-only).

The diff lives in a Tab now

The actual diff moved out of the sidebar into a workspace Tab, so the same surface can show different diff targets:

  • Click a changed file in the sidebar → opens (or focuses) the single working-changes diff tab and scrolls to that file.
  • Click a commit in the sidebar → opens a tab showing that commit's diff.

The diff tab reuses the existing tab system (like the browser/file tabs) — desktop split-pane and compact full-screen come for free. One stable working tab; one tab per commit (re-clicking a commit focuses its tab). Commit tabs are ephemeral on reload.

The sidebar is listing-only

The Changes sidebar is now just a list:

  • Changed files as a collapsible tree or flat list with +/- stats (toggle).
  • The branch's commits ahead of base, each marked local-only () or pushed ().

No inline diffs, no per-commit file tree — to see what's in a commit you click it and view the detailed diff tab. The unified/split + wrap + whitespace controls moved into the diff tab's toolbar.

Inline comments

Inline review comments live in the diff tab, for both working changes and commit diffs (commit comments are namespaced by SHA), and flow to the composer like the existing review flow.

Notes

  • Desktop/large screens; mobile keeps the compact layout.
  • No new diff RPC for commits — a commit's diff composes from the existing listCheckoutCommits + per-file diff into the same renderer the working diff uses, so they look identical.
  • New daemon RPCs (checkout.commits.*) are capability-gated; older hosts simply don't show the commit list.

Refs #117

adradr added 27 commits June 13, 2026 19:27
@greptile-apps

greptile-apps Bot commented Jun 14, 2026

Copy link
Copy Markdown

Greptile Summary

This PR reshapes the git Changes view: the diff moves from the sidebar into a workspace Tab (one stable working-changes tab; one ephemeral tab per commit), while the sidebar becomes a listing-only surface showing changed files and commits ahead of base. The new server RPCs (checkout.commits.list and checkout.commits.file_diff) are capability-gated and additive.

  • New diff tab (diff-panel.tsx) hosts collapsible file sections, the unified/split/wrap/whitespace toolbar, and per-target inline review wiring. Commit diff tabs are ephemeral and stripped from persisted layout on reload via stripEphemeralTabsFromLayout.
  • Commits sidebar section (commits-section/) renders a resizable, collapsible drawer listing commits ahead of base with local () / pushed () indicators and a live pointer-capture drag to resize.
  • Tab identity is extended with a "diff" kind; focusPath is deliberately excluded from identity so re-clicking a file focuses the same tab and only scrolls to the file.

Confidence Score: 4/5

Safe to merge after fixing the commit review key bug; everything else is well-designed and tested.

In diff-panel.tsx, resolveReviewTargetParams includes the live hideWhitespace preference in the commit review draft key even though commit diffs carry no whitespace parameter. Toggling that preference while a commit diff tab is open silently rotates the key, moving any drafted inline comments to a different — effectively unreachable — slot in the store. The user's review attachment empties and any comments they send would be lost. The rest of the PR — the server RPCs, tab identity design, ephemeral-tab stripping, multi-source attachment store, and resize logic — is solid and well-covered by tests.

packages/app/src/panels/diff-panel.tsx — the resolveReviewTargetParams function for the commit branch

Important Files Changed

Filename Overview
packages/app/src/panels/diff-panel.tsx New 921-line diff tab panel: renders collapsible file sections, owns inline review wiring per DiffTarget, and hosts the toolbar. Has a P1 bug where commit review keys vary with the whitespace preference, causing drafted comments to disappear on toggle.
packages/app/src/git/use-diff-files.ts New unified hook that resolves any DiffTarget (working or commit) to ParsedDiffFile[]. Correctly keeps both hook branches always called; fans out per-file commit queries via useQueries; no issues found.
packages/server/src/utils/checkout-git.ts Adds listCheckoutCommits and getCommitFileDiff. Git output is parsed with RS/NUL delimiters to avoid conflicts with arbitrary commit subjects; path injection is guarded before reaching git show; binary-only diffs return null. No issues found.
packages/server/src/server/session/checkout/checkout-session.ts Adds handlers for checkout.commits.list and checkout.commits.file_diff. Validates SHA with assertSafeGitRef and path with a new assertSafeCommitFilePath (no empty, no absolute, no .. segments). No issues found.
packages/app/src/workspace-tabs/identity.ts Extends tab identity with the new "diff" kind. focusPath is correctly excluded from identity (deduplication) but included in workspaceTabTargetsFullyEqual for refresh detection. Clean design.
packages/app/src/stores/workspace-layout-actions.ts Adds stripEphemeralTabsFromLayout to drop commit diff tabs before persisting; uses workspaceTabTargetsFullyEqual in updateExistingTabTarget so focusPath-only re-opens correctly scroll to the new file. No issues found.
packages/app/src/git/commits-section/commits-section.tsx New commits sidebar section with collapsible list and resizable bottom drawer. Drag resize uses pointer capture and DOM listeners correctly cleaned up on unmount. No issues found.
packages/app/src/review/store.ts Adds optional commitSha to review draft key and attachment snapshot, appended at the end so legacy keys remain byte-identical. Additive and backwards-compatible.
packages/app/src/attachments/workspace-attachments-store.ts Adds multi-source support (keyed by sourceKey) to attachment scopes so each diff tab can register its own review attachment without clobbering the sidebar's. Maintains a flattened cache to keep selector references stable. No issues found.
packages/protocol/src/messages.ts Adds CheckoutCommitsList and CheckoutCommitFileDiff request/response schemas, exports ParsedDiffFile from the protocol package, and adds commitsList capability flag. All are additive; existing peers ignore them.
packages/app/src/git/diff-target.ts New minimal module defining DiffTarget discriminated union and diffTargetKey for stable tab identity. ignoreWhitespace is deliberately excluded from the key. Clean, well-tested.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant Sidebar as Changes Sidebar
    participant Store as WorkspaceLayoutStore
    participant Panel as DiffPanel Tab
    participant Server as CheckoutSession

    Sidebar->>Store: openTabFocused diff target + focusPath
    Store-->>Panel: mount DiffPanelBody

    alt Working diff
        Panel->>Server: useCheckoutDiffQuery existing RPC
        Server-->>Panel: ParsedDiffFile array
    else Commit diff
        Panel->>Server: listCheckoutCommits
        Server-->>Panel: commit file list
        Panel->>Server: getCommitFileDiff per file parallel
        Server-->>Panel: ParsedDiffFile per file
    end

    Panel->>Panel: buildReviewDraftKey with commitSha
    Panel->>Panel: useInlineReviewController reviewDraftKey
    Panel->>Store: setWorkspaceAttachments sourceKey equals reviewDraftKey
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant Sidebar as Changes Sidebar
    participant Store as WorkspaceLayoutStore
    participant Panel as DiffPanel Tab
    participant Server as CheckoutSession

    Sidebar->>Store: openTabFocused diff target + focusPath
    Store-->>Panel: mount DiffPanelBody

    alt Working diff
        Panel->>Server: useCheckoutDiffQuery existing RPC
        Server-->>Panel: ParsedDiffFile array
    else Commit diff
        Panel->>Server: listCheckoutCommits
        Server-->>Panel: commit file list
        Panel->>Server: getCommitFileDiff per file parallel
        Server-->>Panel: ParsedDiffFile per file
    end

    Panel->>Panel: buildReviewDraftKey with commitSha
    Panel->>Panel: useInlineReviewController reviewDraftKey
    Panel->>Store: setWorkspaceAttachments sourceKey equals reviewDraftKey
Loading

Reviews (6): Last reviewed commit: "feat(app): make the on-remote commit dot..." | Re-trigger Greptile

Comment thread packages/app/src/git/commits-section/commit-row.tsx Outdated
Comment thread packages/app/src/git/diff-file-body/highlighted-text.tsx
adradr added 13 commits June 14, 2026 16:53
…d-commits

# Conflicts:
#	packages/server/src/server/session.ts
…d-commits

# Conflicts:
#	packages/app/src/git/diff-pane.tsx
#	packages/protocol/src/messages.ts
#	packages/server/src/server/session.ts
#	packages/server/src/server/websocket-server.ts
…d-commits

# Conflicts:
#	packages/server/src/server/session/checkout/checkout-session.test.ts
#	packages/server/src/server/session/checkout/checkout-session.ts
@adradr adradr changed the title Git Changes: file tree with diff stats + per-commit drawer (#117) Git diff: commit history + diff-in-a-tab reshape (#117) Jun 25, 2026
adradr added 3 commits June 25, 2026 13:38
Re-adds the resize handle removed in the sidebar reshape, grafted onto the
listing-only commits section (rows still open diff tabs, no inline file
expansion). Desktop-web only; height persists via commitsSectionHeight
(default 240) and clamps to keep a 160px diff reserve. Render path guards
finiteness + lower bound, and a re-entrancy guard ignores a second concurrent
pointerdown.
Dims the filled green remote dot (row + legend) to ~0.55 opacity so the
local-only ring stays the state that draws the eye.
Comment on lines +356 to +367
focusPath,
}: {
serverId: string;
workspaceId: string;
cwd: string;
target: DiffTarget;
focusPath?: string;
}) {
const { t } = useTranslation();
const { settings } = useAppSettings();
const { preferences, updatePreferences } = useChangesPreferences();
const isCompact = useIsCompactFormFactor();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Commit review key splits when whitespace pref toggles

resolveReviewTargetParams returns ignoreWhitespace: hideWhitespace for commit targets even though getCommitFileDiff has no whitespace parameter — the commit diff content is identical regardless of the preference. As a result, every time a user clicks the "hide whitespace" toolbar button while a commit diff tab is open, reviewDraftKey (which encodes ignoreWhitespace) changes, useInlineReviewController re-subscribes to an empty new key, and all drafted inline comments disappear from the tab and from the composer attachment. The comments are not lost (they remain in the store under the old key) but they are no longer reachable through the current view. Any review the user sends after the toggle contains an empty attachment even if they had added comments before it.

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