[BUG] Windows/Git Bash: git <ref>:<dot-path> arguments silently rewritten, so a mangled command looks like a missing file
Summary
On Windows with Git Bash, the Bash tool silently rewrites git arguments of the form <ref>:<path> when the ref contains a slash and the path starts with a dot. The rewritten argument reaches git as a Windows path list, and git fails to resolve it.
The failure is indistinguishable from "that file does not exist in that ref", which is what makes it costly: git show <branch>:.<something> is the natural way to check whether a file is present on a branch, and a mangled argument and a genuinely absent file produce the same practical outcome — nothing.
Repro
In any git repo on Windows, via the Bash tool (Git Bash):
git show 'origin/main:.github/workflows/ci.yml'
Actual:
fatal: ambiguous argument 'origin\main;.github\workflows\ci.yml': unknown revision or path not in the working tree.
Note both transformations: / became \, and the : became ;. MSYS has treated the argument as a colon-separated PATH list and converted it to Windows form.
Which shapes are affected
Measured on Git for Windows, same repo, same command shape:
| Argument | Result |
|---|---|
| origin/main:home/CLAUDE.md | ok |
| origin/main:.githooks/post-merge | mangled |
| origin/feat/some-branch:home/CLAUDE.md | ok |
| origin/feat/some-branch:.githooks/post-merge | mangled |
| HEAD:.githooks/post-merge | ok |
| HEAD:home/CLAUDE.md | ok |
So the trigger is specifically: a ref containing a slash, plus a path beginning with a dot. A HEAD: ref is safe, and a non-dotted path is safe. That narrowness is part of the problem — the same command works for most paths, so the behaviour reads as "this file is missing" rather than "this invocation is broken".
Dot-directories are common in exactly the files an agent tends to inspect: .github/, .gitea/, .claude/, .specify/, .githooks/, .vscode/.
Why it matters for an agent specifically
An agent reasons from command output. Here the output is a plausible negative, so the wrong conclusion is reached confidently and then acted on. In our case a git show <branch>:.specify/memory/constitution.md returned nothing, that was read as "the file is not on this branch", and three repositories were reported as having adopted a config file when none of them had. Several follow-up checks appeared to confirm it — but every one of them went through the same mangling, so the agreement was one failure repeated, not corroboration.
Workarounds (both verified on every failing case above)
MSYS_NO_PATHCONV=1 MSYS2_ARG_CONV_EXCL='*' git show 'origin/main:.github/workflows/ci.yml'
or run the command through PowerShell, which has no MSYS layer.
Suggested fix
Any of these would remove the class of error:
- Set
MSYS_NO_PATHCONV=1/MSYS2_ARG_CONV_EXCL='*'in the environment the Bash tool creates on Windows, at least forgitinvocations. - Detect the
<ref>:<dot-path>shape in a Bash command on Windows and either apply the guard automatically or warn. - Surface the mangling: if git reports
ambiguous argumentand the quoted argument differs from what was sent, say so. Right now the difference between the sent and received argument is visible in the error text but easy to read past.
Option 1 seems least surprising — the current behaviour converts arguments the caller did not intend as paths.
Environment
- Windows 11 Pro 26100
- Git for Windows (Git Bash), used as the Bash tool shell
- Reproduced consistently; not intermittent