Skip to content

Diff() reports renames without DetectRenames() (git's diff.renames default), so it disagrees with Patch() and rename detection can't be turned off #136

Description

@matt-edmondson

What's wrong

GitDiffBuilder (GitIntegration/Builders/GitDiffBuilder.cs ~L172-180) adds --find-renames / --find-copies only when requested and never passes --no-renames. Git has defaulted diff.renames=true since 2.9, so rename detection is effectively always on, and its behavior depends on the host's config. GitPatchBuilder already pins this (arguments.Add(_detectRenames ? "--find-renames" : "--no-renames"), the #121 fix), so the two builders now disagree.

Failure scenario (reproduced with a library-level test)

  1. Commit old.txt, then git mv old.txt new.txt.
  2. repo.Diff().Staged() — no DetectRenames() — returns Renamed old.txt -> new.txt.
  3. repo.Patch().Staged() returns Added new.txt; Deleted old.txt.

Consequences:

  • DetectRenames() is a no-op in a default git setup; callers cannot turn rename detection off.
  • A staging UI that takes its file list from Diff() and hunks from Patch() can't match entries up.
  • Results vary by host: diff.renames=false turns renames off; diff.renames=copies emits copy (C) entries without DetectCopies().

Suggested fix

Always set rename detection explicitly, mirroring GitPatchBuilder: emit --find-copies if _detectCopies, else --find-renames if _detectRenames, else --no-renames. Update the DetectRenames()/DetectCopies() XML docs to state detection is off unless requested, regardless of diff.renames (matching IGitPatchBuilder.DetectRenames).

Acceptance criteria

  • Diff().Staged() without DetectRenames() reports Added + Deleted for a git mv, matching Patch().
  • With DetectRenames() it reports Renamed.
  • Tests run with diff.renames set to true, false and copies in the repo config and produce identical results.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingreadyFully specified; implement as written

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions