From 5edd1be7bf58ddbc7453ffbadc4862c8c1297a43 Mon Sep 17 00:00:00 2001 From: Stuart Saunders Date: Sun, 5 Jul 2026 10:42:25 -1000 Subject: [PATCH] =?UTF-8?q?fix(git):=20=F0=9F=90=9B=20exclude=20untracked?= =?UTF-8?q?=20files=20from=20ref-range=20diffs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - #11 enabled includeUntracked for the whole default case (bare refs) - That catch-all also covers A..B ranges with both endpoints pinned - Untracked overlay made range diffs disagree with git diff A..B - Gate inclusion on ref not being a range; bare refs keep #10 behavior --- packages/git/src/diff.ts | 6 +++++- packages/git/tests/get-diff-files.test.ts | 22 ++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/packages/git/src/diff.ts b/packages/git/src/diff.ts index b13a9f2..c7f7191 100644 --- a/packages/git/src/diff.ts +++ b/packages/git/src/diff.ts @@ -38,7 +38,11 @@ export function resolveDiffArgs(ref: string): RefDiffArgs { case 'work': return { type: 'args', args: ['HEAD'], includeUntracked: true }; default: - return { type: 'args', args: [normalizeRef(ref)], includeUntracked: true }; + // Bare refs (`diffity main`) diff against the working tree, so untracked + // files are part of the change set (#10). Ranges (`A..B`) pin both + // endpoints — the working tree isn't involved, so untracked files must + // be excluded or the diff won't match `git diff A..B`. + return { type: 'args', args: [normalizeRef(ref)], includeUntracked: !ref.includes('..') }; } } diff --git a/packages/git/tests/get-diff-files.test.ts b/packages/git/tests/get-diff-files.test.ts index ec3684d..0b1ad05 100644 --- a/packages/git/tests/get-diff-files.test.ts +++ b/packages/git/tests/get-diff-files.test.ts @@ -86,6 +86,28 @@ describe('getDiffFiles', () => { git('checkout -- base.txt'); }); + it('includes untracked files for bare refs (diff against working tree)', async () => { + const { getDiffFiles } = await import('../src/diff.js'); + writeFile('untracked-file.txt', 'untracked\n'); + + const files = getDiffFiles('main'); + expect(files).toContain('untracked-file.txt'); + + execSync(`rm "${join(repoDir, 'untracked-file.txt')}"`, { stdio: 'pipe' }); + }); + + it('excludes untracked files for range refs (both endpoints pinned)', async () => { + const { getDiffFiles } = await import('../src/diff.js'); + writeFile('untracked-file.txt', 'untracked\n'); + + const files = getDiffFiles('main..feature'); + expect(files).toContain('feature.txt'); + expect(files).toContain('base.txt'); + expect(files).not.toContain('untracked-file.txt'); + + execSync(`rm "${join(repoDir, 'untracked-file.txt')}"`, { stdio: 'pipe' }); + }); + it('returns working tree files for work ref', async () => { const { getDiffFiles } = await import('../src/diff.js'); writeFile('untracked-file.txt', 'untracked\n');