Skip to content

GitPatchBuilder doesn't pin context lines or rename detection, so host diff.context=0 yields patches Apply can't stage #121

Closed

Description

@matt-edmondson

What's wrong

GitPatchBuilder pins host settings that would otherwise change the shape of the patch: prefixes, color, ext-diff, textconv and suppressBlankEmpty. That follows the repo's stated policy. Two settings are not pinned (GitIntegration/Builders/GitPatchBuilder.cs:~180-188).

Context lines

-U is only passed when WithContext(n) is called. WithContext(0) is deliberately refused, because a zero-context hunk needs --unidiff-zero to apply. The default path, where WithContext is never called, instead inherits diff.context from git config.

In a repository with diff.context=0, changing line 25 of a 50-line file produces @@ -25 +25 @@. Feeding that patch to Apply(...).ToIndex() fails with error: patch failed: f.txt:25. This is the failure the WithContext remarks say the builder prevents, and it is reported against the index rather than the config setting.

Rename and copy detection

--find-renames is only added when DetectRenames() is called. Nothing turns renames off otherwise, and git enables them by default:

  • Staged renames come back as Renamed even without DetectRenames().
  • With diff.renames=copies, git emits copy from / copy to headers. The parser ignores those, so a new copied file is reported as Kind = Modified with OriginalPath = null.

Suggested fix

  • Always emit -U{_contextLines ?? 3}.
  • Emit --no-renames unless DetectRenames() was called.
  • Optionally, recognise copy from / copy to in GitPatchParser.ApplyHeaderLine.
  • Add a builder test asserting the argument list contains -U3 and --no-renames by default. Add an integration test with diff.context=0 set in the fixture repository, asserting the patch round-trips through Apply(...).ToIndex().

Activity

  1. matt-edmondson commented on Sep 26, 2026

    @matt-edmondson
    ContributorAuthor

    Triage

    • Category: Bug
    • Priority: Medium. Patches come out in a shape Apply(...).ToIndex() cannot stage, but only when the host sets diff.context=0 or diff.renames=copies. That is uncommon, but it goes against the builder's stated pin-everything policy.
    • Area / suggested owner: GitPatchBuilder argument construction, optionally with GitPatchParser.ApplyHeaderLine
    • Duplicates / in progress: None found. It is related to Patch() misreports paths containing " b/" and throws for the whole repo when any file name is C-quoted by git #120 (the same patch pipeline, parser side). No open PR references this issue.

    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions