Git commit history (#1534)

* feat(app): add fileView preference for changes panel

* feat(app): add buildDiffTree util for changed-files tree

* feat(app): add changed-files tree directory row

* feat(app): changed-files tree view mode in changes panel (#117)

* feat(protocol): add checkout.commits.list RPC + commitsList feature flag

* feat(server): list branch commits ahead of base with on-remote flags

* feat(server): handle checkout.commits.list RPC and advertise capability

* feat(client): checkout.commits.list method + useCommitsQuery hook

* feat(app): per-commit inline view with local-vs-remote markers (#117)

* feat(protocol,server): per-commit file diff RPC (checkout.commits.file_diff)

* feat(app): open per-commit file diff on click (#117)

* refactor: surface baseRef + commits loading/error, drop dead depth field

* fix(app): flip commit local/remote dot — local hollow, remote filled

* feat(app): list/tree view for expanded commit file list (#117)

* fix(app): syntax-highlight per-commit file diff to match Changes view

* feat(app): draggable resize between commits and diff sections

* refactor(app): dedupe wrap-text helpers into diff-highlighted-text

* fix(app): clean up commits resize drag on unmount + a11y label

* fix(app): collapse commits section by default

* fix(app): render per-commit file diff with the shared Changes line renderer

* perf(app): memoize shared diff line row; drop redundant DiffLineView wrapper

* refactor(app): extract shared DiffFileBody; render commit file diff through it

* fix(app): hide inline-comment affordance in per-commit diffs (no reviewActions)

* feat(app): move commits to a resizable bottom drawer in the Changes panel

* feat(review): commitSha scoping for per-commit review drafts + attachment

* feat(app): per-commit inline comments wired through to the composer (#117)

* refactor(app): own commit file-diff open state in CommitFileList (drop reset effect)

* refactor(app): colocate diff-render cluster under git/diff-file-body/

* feat(app): add diff tab target kind (working/commit diff tabs)

* feat(app): useDiffFiles hook unifying working + commit diff targets

* feat(app): diff tab panel rendering working/commit diffs

* feat(app): open a commit diff tab on commit click; drop per-commit drawer/file list

* feat(app): open/scroll working diff tab on changed-file click

* fix(app): keep commit diff tabs ephemeral; align working diff whitespace

* feat(app): collapsible file sections in the diff tab, collapsed by default

* feat(app): make the on-remote commit dot more subtle

Dims the filled green remote dot (row + legend) to ~0.55 opacity so the
local-only ring stays the state that draws the eye.

* Reshape commit diffs around the existing Changes view

* Fix diff tab migration complexity after rebase

* Address diff tab review findings

* Clean up diff tab review interfaces

* Collapse commit diffs into the existing view

* Load commits when expanded

---------

Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com>
This commit is contained in:
adradr
2026-07-16 17:36:41 +02:00
committed by GitHub
co-authored by Mohamed Boudra
parent 5da6548aff
commit 0d3b717cf3
44 changed files with 2843 additions and 439 deletions
+69
View File
@@ -1644,6 +1644,37 @@ export const CheckoutGithubSetAutoMergeRequestSchema = z.object({
requestId: z.string(),
});
const CheckoutCommitFileSchema = z.object({
path: z.string(),
additions: z.number(),
deletions: z.number(),
status: z.enum(["added", "modified", "deleted", "renamed"]).optional(),
});
const CheckoutCommitSchema = z.object({
sha: z.string(),
shortSha: z.string(),
subject: z.string(),
authorName: z.string(),
authorDate: z.string(), // ISO 8601
isOnRemote: z.boolean(), // false = local-only (unpushed)
files: z.array(CheckoutCommitFileSchema),
});
export const CheckoutCommitsListRequestSchema = z.object({
type: z.literal("checkout.commits.list.request"),
cwd: z.string(),
requestId: z.string(),
});
export const CheckoutCommitFileDiffRequestSchema = z.object({
type: z.literal("checkout.commits.file_diff.request"),
cwd: z.string(),
sha: z.string(),
path: z.string(),
requestId: z.string(),
});
const GitHubRepoSegmentSchema = z.string().regex(/^[A-Za-z0-9._-]+$/);
export const CheckoutGithubGetCheckDetailsRequestSchema = z.object({
@@ -2246,6 +2277,8 @@ export const SessionInboundMessageSchema = z.discriminatedUnion("type", [
CheckoutPrCreateRequestSchema,
CheckoutPrMergeRequestSchema,
CheckoutGithubSetAutoMergeRequestSchema,
CheckoutCommitsListRequestSchema,
CheckoutCommitFileDiffRequestSchema,
CheckoutGithubGetCheckDetailsRequestSchema,
CheckoutPrStatusRequestSchema,
PullRequestTimelineRequestSchema,
@@ -2523,6 +2556,8 @@ export const ServerInfoStatusPayloadSchema = z
workspaceGithubRepositorySearch: z.boolean().optional(),
// COMPAT(projectCreateDirectory): added in v0.1.108, remove gate after 2027-01-15.
projectCreateDirectory: z.boolean().optional(),
// COMPAT(commitsList): added in v0.1.110, remove gate after 2027-01-16.
commitsList: z.boolean().optional(),
// COMPAT(providerRemoval): added in v0.1.105, drop the gate when floor >= v0.1.105.
providerRemoval: z.boolean().optional(),
})
@@ -3794,6 +3829,31 @@ export const CheckoutGithubSetAutoMergeResponseSchema = z.object({
}),
});
export const CheckoutCommitsListResponseSchema = z.object({
type: z.literal("checkout.commits.list.response"),
payload: z.object({
cwd: z.string(),
baseRef: z.string().nullable(),
commits: z.array(CheckoutCommitSchema),
error: CheckoutErrorSchema.nullable(),
requestId: z.string(),
}),
});
export const CheckoutCommitFileDiffResponseSchema = z.object({
type: z.literal("checkout.commits.file_diff.response"),
payload: z.object({
cwd: z.string(),
sha: z.string(),
path: z.string(),
// null when the file is absent from the commit or carries no textual diff
// (e.g. binary-only changes).
file: ParsedDiffFileSchema.nullable(),
error: CheckoutErrorSchema.nullable(),
requestId: z.string(),
}),
});
const CheckoutGithubCheckAnnotationSchema = z.object({
path: z.string().optional(),
startLine: z.number().optional(),
@@ -4571,6 +4631,8 @@ export const SessionOutboundMessageSchema = z.discriminatedUnion("type", [
CheckoutPrCreateResponseSchema,
CheckoutPrMergeResponseSchema,
CheckoutGithubSetAutoMergeResponseSchema,
CheckoutCommitsListResponseSchema,
CheckoutCommitFileDiffResponseSchema,
CheckoutGithubGetCheckDetailsResponseSchema,
CheckoutPrStatusResponseSchema,
PullRequestTimelineResponseSchema,
@@ -4883,6 +4945,13 @@ export type CheckoutPushRequest = z.infer<typeof CheckoutPushRequestSchema>;
export type CheckoutPushResponse = z.infer<typeof CheckoutPushResponseSchema>;
export type CheckoutRefreshRequest = z.infer<typeof CheckoutRefreshRequestSchema>;
export type CheckoutRefreshResponse = z.infer<typeof CheckoutRefreshResponseSchema>;
export type CheckoutCommitFile = z.infer<typeof CheckoutCommitFileSchema>;
export type CheckoutCommit = z.infer<typeof CheckoutCommitSchema>;
export type CheckoutCommitsListRequest = z.infer<typeof CheckoutCommitsListRequestSchema>;
export type CheckoutCommitsListResponse = z.infer<typeof CheckoutCommitsListResponseSchema>;
export type CheckoutCommitFileDiffRequest = z.infer<typeof CheckoutCommitFileDiffRequestSchema>;
export type CheckoutCommitFileDiffResponse = z.infer<typeof CheckoutCommitFileDiffResponseSchema>;
export type ParsedDiffFile = z.infer<typeof ParsedDiffFileSchema>;
export type CheckoutPrCreateRequest = z.infer<typeof CheckoutPrCreateRequestSchema>;
export type CheckoutPrCreateResponse = z.infer<typeof CheckoutPrCreateResponseSchema>;
export type CheckoutPrMergeRequest = z.infer<typeof CheckoutPrMergeRequestSchema>;