Skip to content

Pin context lines and rename detection in Patch() - #128

Merged
matt-edmondson merged 1 commit into
mainfrom
fix/patch-pin-context-renames
Sep 27, 2026
Merged

matt-edmondson merged 1 commit into
mainfrom
fix/patch-pin-context-renames

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Fixes #121

What changed

GitPatchBuilder pinned the prefixes, color, ext-diff, textconv and suppressBlankEmpty, but two settings still came from the host's git config:

  • Context lines. The builder only passed -U when WithContext(n) was called. It now always passes -U3, or the WithContext value. Before this, a repository with diff.context=0 produced @@ -25 +25 @@ hunks, and Apply(...).ToIndex() failed on them with error: patch failed: f.txt:25.
  • Rename detection. The builder now passes --no-renames unless DetectRenames() was called, in which case it passes --find-renames as before. Before this, git's default rename detection, or diff.renames=copies, decided the patch shape instead of the builder.

The doc comments on WithContext and DetectRenames now say that the default ignores the host's config.

I left out the issue's optional copy from / copy to parsing. With --no-renames or --find-renames always on the command line, git no longer emits copy headers for this builder.

Tests

  • BuildsTheDefaultPatchVector now expects -U3 and --no-renames at the end of the vector.
  • New PinsContextAndRenameDetectionWhenNeitherIsRequested and ExplicitContextAndRenamesReplaceThePinnedDefaults check the argument list.
  • New integration test RoundTripsUnderZeroContextConfigurationAsync sets diff.context=0 in the fixture repository, changes line 25 of 50, and checks that the patch goes back through Apply(...).ToIndex().
  • New integration test ReportsAStagedRenameAsDeleteAndAddUnlessRequestedAsync sets diff.renames=copies. It checks that a staged rename comes back as a delete plus an add by default, and as Renamed with OriginalPath when DetectRenames() is called.

With the builder change reverted, all four fail. The zero-context test fails with the error from the issue, patch failed: f.txt:25. With the change, the full suite passes: 712 tests, 0 failed.

🤖 Generated with Claude Code

https://claude.ai/code/session_01VKxYoUXQqgRKJR6ynbvnms


Generated by Claude Code

Patch() now always passes -U3 (or the WithContext value) and passes
--no-renames unless DetectRenames() was called. Before, a host with
diff.context=0 produced zero-context hunks that Apply(...).ToIndex()
could not stage, and git's default rename detection (or
diff.renames=copies) decided the patch shape instead of the builder.

Fixes #121

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VKxYoUXQqgRKJR6ynbvnms
@sonarqubecloud

Copy link
Copy Markdown

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.

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

2 participants