diff --git a/src/main/services/git/GitService.ts b/src/main/services/git/GitService.ts index 54917ac1..2451c91c 100644 --- a/src/main/services/git/GitService.ts +++ b/src/main/services/git/GitService.ts @@ -758,9 +758,17 @@ export class GitService { } } } else { - // Regular commit: use show --name-status - const commitShow = await git.show([trimmedHash, '--name-status', '--pretty=format:%P']); - const lines = commitShow.split('\n').filter((line) => line.trim()); + // Regular commit: use diff-tree to list changed files without patch output. + // `--root` ensures the initial commit reports its files too. + const diffTree = await git.raw([ + 'diff-tree', + '--root', + '--no-commit-id', + '--name-status', + '-r', + trimmedHash, + ]); + const lines = diffTree.split('\n').filter((line) => line.trim()); for (const line of lines) { // Match: status (with optional percentage for R/C) and file path(s) diff --git a/src/renderer/components/source-control/CommitDiffViewer.tsx b/src/renderer/components/source-control/CommitDiffViewer.tsx index aecfadc5..1488a3c9 100644 --- a/src/renderer/components/source-control/CommitDiffViewer.tsx +++ b/src/renderer/components/source-control/CommitDiffViewer.tsx @@ -8,6 +8,7 @@ interface CommitDiffViewerProps { rootPath: string; fileDiff: FileDiff | null | undefined; filePath: string | null; + commitHash: string | null; isActive?: boolean; isLoading?: boolean; onPrevFile?: () => void; @@ -20,6 +21,7 @@ export function CommitDiffViewer({ rootPath, fileDiff, filePath, + commitHash, isActive = true, isLoading = false, onPrevFile, @@ -65,6 +67,7 @@ export function CommitDiffViewer({ isActive={isActive} diff={diffData} isCommitView + commitHash={commitHash} onPrevFile={onPrevFile} onNextFile={onNextFile} hasPrevFile={hasPrevFile} diff --git a/src/renderer/components/source-control/DiffViewer.tsx b/src/renderer/components/source-control/DiffViewer.tsx index d8f754ec..1fdae1d1 100644 --- a/src/renderer/components/source-control/DiffViewer.tsx +++ b/src/renderer/components/source-control/DiffViewer.tsx @@ -115,6 +115,7 @@ interface DiffViewerProps { diff?: FileDiff; skipFetch?: boolean; isCommitView?: boolean; // Add flag to indicate commit history view + commitHash?: string | null; // Used to scope Monaco models in commit view } export function DiffViewer({ @@ -128,6 +129,7 @@ export function DiffViewer({ diff: externalDiff, skipFetch = false, isCommitView = false, + commitHash = null, }: DiffViewerProps) { const sessionId = useActiveSessionId(rootPath); const { t } = useI18n(); @@ -726,6 +728,9 @@ export function DiffViewer({ setEditorReady(true); const currentModel = editor.getModel(); + const mountedModels = currentModel + ? { original: currentModel.original, modified: currentModel.modified } + : null; if (currentModel) { modelsRef.current.original = currentModel.original; modelsRef.current.modified = currentModel.modified; @@ -787,9 +792,16 @@ export function DiffViewer({ for (const d of disposables) { d.dispose(); } + // Prevent commit-view Monaco models from accumulating in memory. + // We intentionally keep worktree models cached for performance, but commit history + // can generate many unique models (commitHash scoped URIs), so dispose on unmount. + if (isCommitView && mountedModels) { + mountedModels.original?.dispose(); + mountedModels.modified?.dispose(); + } }; }, - [file?.path, performAutoNavigation] + [file?.path, performAutoNavigation, isCommitView] ); // Toggle hide unchanged regions @@ -1200,11 +1212,25 @@ export function DiffViewer({