Skip to content

Read files from the worktree git dir instead of the shared repository#1227

Open
veewee wants to merge 1 commit into
phpro:v2.xfrom
veewee:bugfix/worktree-file-listing
Open

Read files from the worktree git dir instead of the shared repository#1227
veewee wants to merge 1 commit into
phpro:v2.xfrom
veewee:bugfix/worktree-file-listing

Conversation

@veewee

@veewee veewee commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

What is wrong

Inside a linked git worktree, GrumPHP lists and diffs files against the main repository's branch instead of the worktree's own. A task then fails on a file that exists on main but not in the worktree:

yamllint: SplFileInfo::openFile(config/services/commands.yaml):
          Failed to open stream: No such file or directory

The git CLI in the same directory is right. git ls-files there returns the worktree's branch and never mentions commands.yaml. Only GrumPHP sees main's files.

Why it happens

A worktree's .git is a file that points at <main>/.git/worktrees/<id>, and that directory's commondir points back to the shared <main>/.git. GrumPHP collapsed a worktree straight to that shared directory and used it for everything, including the git client that lists files. So the client ran git --git-dir=<main>/.git ls-files and read main's index.

Because gitonomy passes --git-dir on the command line, it overrides GIT_DIR. A container that exports the correct GIT_DIR and GIT_WORK_TREE fixes the bare git CLI but cannot reach GrumPHP, so the fix has to live here.

Collapsing to the shared directory is not wrong on its own. It is correct for hooks, because a worktree runs the main repository's hooks. The mistake was reusing that same directory to list files.

The fix

Separate the two concerns.

flowchart TD
    W["worktree .git file"] --> R{resolve}
    R -->|hooks| C["shared main/.git"]
    R -->|files and diffs| O["main/.git/worktrees/id"]
    C --> H["install and run hooks"]
    O --> L["ls-files and diff read the worktree branch"]
Loading

Hooks still resolve to the shared .git, so hook install, deinit, and execution are unchanged. The git client that lists files and reads diffs now points at the worktree's own git dir, so ls-files and staged diffs follow the worktree's branch. A normal checkout and a submodule resolve exactly as before, so this is a no-op outside worktrees.

GRUMPHP_GIT_REPOSITORY_DIR still overrides the resolved directory. It now drives both the hooks dir and the file-listing dir, which is how it behaved before the split, so anyone already setting it keeps the same result.

Inside a linked git worktree, GrumPHP listed and diffed files against the main
repository's branch instead of the worktree's own. A task could then fail on a
file that exists on main but not in the worktree:

    yamllint: SplFileInfo::openFile(config/services/commands.yaml):
              Failed to open stream: No such file or directory

A worktree's .git is a file pointing at <main>/.git/worktrees/<id>, and that
directory's commondir points back to the shared <main>/.git. GrumPHP collapsed
the worktree straight to that shared directory and used it for everything,
including the git client that lists files. So "git --git-dir=<main>/.git
ls-files" returned main's index. The gitonomy client passes --git-dir on the
command line, which overrides GIT_DIR, so correcting the environment around
GrumPHP could not reach it.

Collapsing to the shared directory is correct for hooks: a worktree runs the
main repository's hooks. So the two concerns are now separate. Hooks still
resolve to the shared .git; the git client that lists files and reads diffs
points at the worktree's own git dir. A normal checkout and a submodule resolve
as before.

GRUMPHP_GIT_REPOSITORY_DIR still overrides the resolved directory and now drives
both the hooks dir and the file-listing dir, which matches how it behaved before
the split.
@veewee
veewee marked this pull request as draft July 17, 2026 13:51
@veewee
veewee marked this pull request as ready for review July 17, 2026 14:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant