case-collision
worktree
repo whose history holds src/File.ts and src/file.ts — a case-only path collision invisible on case-insensitive filesystems
Description
The git object store contains two paths that differ only by case:
`src/File.ts` (PascalCase) and `src/file.ts` (lowercase). They
co-exist in git's history but collide on case-insensitive filesystems.
Both entries are accessible via git plumbing regardless of platform:
git show HEAD:src/File.ts # the PascalCase variant
git show HEAD:src/file.ts # the lowercase variant
git ls-tree -r HEAD # lists both as distinct paths
Platform notes:
- Linux (case-sensitive FS): `git checkout HEAD -- src/` creates both
files without conflict. The scenario leaves them off disk — both
show as "deleted" in the working tree.
- macOS / Windows (case-insensitive FS, the default): the OS maps
`File.ts` and `file.ts` to the same physical inode. Checking out
the commit silently overwrites one variant with the other, losing
data. This is the cross-platform footgun the scenario documents.
- `core.ignoreCase=false` is set explicitly so git exposes both
entries on all host platforms, including macOS where `git init`
would otherwise auto-detect `ignoreCase=true`.
Useful for testing:
- Case-collision detection and warnings in status / diff views
- Tools that verify a repo is safe to clone on case-insensitive FS
- `git ls-tree` output parsing (two entries, same prefix, case only) Contracts
- main is checked out
- main has 2 commits
- HEAD tree contains src/File.ts (PascalCase variant)
- HEAD tree contains src/file.ts (lowercase variant)
- both case variants are absent from the working tree
- core.ignoreCase is false
Tags
Branches
main Use it
import { spinUpScenario } from '@gfargo/git-scenarios'
const repo = await spinUpScenario('case-collision') npx git-scenarios create case-collision import { describeWithScenario } from '@gfargo/git-scenarios/jest'
describeWithScenario('case-collision', (getRepo) => {
it('should have the expected state', async () => {
const repo = getRepo()
// your assertions here
})
}) Commit graph
* ad7c59b (HEAD -> main) feat: add case-colliding sources
* 7520170 chore: initial