You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Patch() misreports paths containing " b/" and throws for the whole repo when any file name is C-quoted by git #120
GitPatchParser.ReadPathFromFileStart (GitIntegration/Parsing/GitPatchParser.cs:~191-206) finds the new-side path in a diff --git a/X b/Y header by taking whatever follows the last" b/". That fails in two ways.
1. Wrong path when the name contains b/
If you modify Plan b/notes.txt, git emits:
diff --git a/Plan b/notes.txt b/Plan b/notes.txt
The last b/ is inside the new-side path, so GitFilePatch.Path comes back as notes.txt. The code comment says searching from the end protects against the old side containing b/. It doesn't, because without a rename the new side is the same text as the old side.
The patch is silently attributed to the wrong file. A staging UI shows the wrong name, and ForPath(file.Path) or Unstage(file.Path) targets a different file, or none.
2. One quoted name makes the whole call throw
core.quotepath=false only turns off escaping of non-ASCII characters. Git still C-quotes names that contain ", \, a tab or a control character:
diff --git "a/say \"hi\".txt" "b/say \"hi\".txt"
That header has no b/, so Patch() throws GitParseException: A diff header has no recognizable new-side path. One legally named file on Linux or macOS makes the patch for every other file in the repository unreadable. Diff() copes with the same file because it uses -z.
rename from / rename to lines (ApplyHeaderLine, around line 212) are quoted the same way and aren't unquoted either.
Suggested fix
No rename or copy: the old and new paths are identical. Split a/P b/P at the midpoint and check that both halves match. This is the approach git's own git_header_name takes.
Otherwise: take the path from the +++ b/… line (stripping the trailing tab git appends when a path contains a space) or from rename to.
Quoted operands: when an operand starts with ", decode git's C escapes (\", \\, \t, \n, octal \NNN UTF-8 bytes) before building the RelativeFilePath. Do the same for rename from / rename to.
Add parser fixtures for Plan b/notes.txt and for say "hi".txt.
Notes: The midpoint split that git itself uses (git_header_name) fixes the no-rename case without guessing. The quoted-operand decoder can be shared with the rename from/rename to handling.
Activity
matt-edmondson commentedon Sep 26, 2026
Triage
b/makes the parser silently attach the patch to the wrong file, so staging calls likeForPathandUnstageact on the wrong target.Patch()throw for the entire repository.GitPatchParser(ReadPathFromFileStart,ApplyHeaderLine)git_header_name) fixes the no-rename case without guessing. The quoted-operand decoder can be shared with therename from/rename tohandling.Generated by Claude Code