Re: diff --cached --no-ext-diff --find-copies-harder --quiet exits with wrong status code
- From
D. Ben Knoble <ben.knoble@gmail.com>
- Date
- Nov 8, 2025, 19:08 UTC
- Message-ID
- <CALnO6CBsXEpeCTS=FpcOvXEOw7sNGT8fdb4Z8PBewoW0iRMnXQ@mail.gmail.com>
- In-Reply-To
- <CALnO6CBsj+aMvHJoUQ+LHAtXhcFhQeH8AuHyrX+rumur6MQQog@mail.gmail.com>
On Sat, Nov 8, 2025 at 2:05 PM D. Ben Knoble <ben.knoble@gmail.com> wrote:
Show 29 quoted lines
>
> AFAICT, you need all of the mentioned options to trigger the bug.
> Allowing ext-diff works fine, I don't think it's triggered in
> non-cached diffs, and I've never seen it without --find-copies-harder.
> Notably, s/quiet/exit-code works just fine.
>
> Here's a repro from git.git:
>
> cp git{,1}.c
> git add git1.c
> git diff --cached --no-ext-diff --quiet --find-copies-harder &&
> echo 'this should exit 1!'
>
> (And of course, ^quiet^exit-code if your shell supports it yields a
> different outcome)
>
> Context: my distro applies a patch that allows
> diff.renames=copies-harder. In a repo with that turned on,
> git-prompt.sh stopped showing some staged changes. Turns out it runs
> git diff with all these flags (less --find-copies-harder, which is
> enabled by the config option). I _have_ confirmed this bug exists in
> unpatched Git, however.
>
> Some rough debugging notes: when entering diffcore_std (or
> diffcore_rename_extended's cleanup loop):
> - for exit-code, diff_queued_diff.nr matches "git ls-files :/ | wc -l"
> - for quiet, it's just 1 (the first file listed by git ls-files :/, AFAICT)
> The only other obvious difference I spotted is that the "quick" flag
> is turned on for quiet, which makes sense.Ah, woops. The reason this matters is that, after diff_rename, in the correct version the queue is non-empty and has_changes gets set, which plays into diff_result_code. In the broken version, the resulting queue ends up empty, so has_changes is _reset_ to 0 (despite previously being 1?)
I think I also spotted a difference in diff_from_contents, but not sure if that's relevant.
-- D. Ben Knoble