Skip to content

case-collision

worktree

repo whose history holds src/File.ts and src/file.ts — a case-only path collision invisible on case-insensitive filesystems

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)
  • 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
case-collisionfilesystemcross-platform
main
import { spinUpScenario } from '@gfargo/git-scenarios'

const repo = await spinUpScenario('case-collision')
* ad7c59b (HEAD -> main) feat: add case-colliding sources
* 7520170 chore: initial

Back to Scenario Browser