From 393cae14bf98dbf903bc8d333a41e058127e68fa Mon Sep 17 00:00:00 2001 From: cye2 Date: Wed, 15 Apr 2026 17:26:18 +0800 Subject: [PATCH] =?UTF-8?q?fix(git):=20=E4=BF=AE=E5=A4=8D=E6=8F=90?= =?UTF-8?q?=E4=BA=A4=E5=8E=86=E5=8F=B2=E6=96=87=E4=BB=B6=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E4=B8=8E=20diff=20=E8=A7=86=E5=9B=BE=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 使用 `git diff-tree --root` 获取普通提交的变更文件列表,避免 `git show` 输出补丁导致解析异常 - 提交历史 Diff Viewer 按 `commitHash` 隔离 Monaco model URI,并在卸载时释放 commit-view models,防止内存累积 --- src/main/services/git/GitService.ts | 14 ++++++-- .../source-control/CommitDiffViewer.tsx | 3 ++ .../components/source-control/DiffViewer.tsx | 34 ++++++++++++++++--- .../source-control/SourceControlPanel.tsx | 1 + 4 files changed, 45 insertions(+), 7 deletions(-) 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({
{diff && diff.original != null && diff.modified != null && isThemeReady && (