git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH] diff: ensure consistent diff behavior with -I<regex> across output formats

From
Lidong Yan <yldhome2d2@gmail.com>
Date
Aug 3, 2025, 08:42 UTC
Message-ID
<2C9BB1AD-A958-4AE6-9B85-E57437D00535@gmail.com>
In-Reply-To
<20250802102249.GA3738980@coredump.intra.peff.net>
On Sun, Aug 2, 2025 at 06:22PM, Jeff King <peff@peff.net> wrote:
Show 43 quoted lines
> 
> So here's a naive application of the same technique:
> 
> diff --git a/diff.c b/diff.c
> index 76291e238c..0fe6eb7443 100644
> --- a/diff.c
> +++ b/diff.c
> @@ -6845,8 +6845,28 @@ void diff_flush(struct diff_options *options)
>     DIFF_FORMAT_CHECKDIFF)) {
> for (i = 0; i < q->nr; i++) {
> struct diff_filepair *p = q->queue[i];
> - if (check_pair_status(p))
> - flush_one_pair(p, options);
> +
> + if (!check_pair_status(p))
> + continue;
> +
> + if (options->flags.diff_from_contents) {
> + FILE *orig_out = options->file;
> + int orig_changes = options->found_changes;
> + int skip;
> +
> + options->file = xfopen("/dev/null", "w");
> + diff_flush_patch(p, options);
> + skip = !options->found_changes;
> +
> + fclose(options->file);
> + options->file = orig_out;
> + options->found_changes = orig_changes;
> +
> + if (skip)
> + continue;
> + }
> +
> + flush_one_pair(p, options);
> }
> separator++;
> }
> 
> which works on a trivial example. It affects all of raw, name-only,
> name-status, and checkdiff. I know Junio said that --raw should not be
> affected, but I'm not sure I agree. Anyway, it should be possible to
> split the logic by output type.
I think I could do the same thing in diffcore_ignore(). Like:

+void diffcore_ignore(struct diff_options *o) +{ + struct diff_queue_struct *q = &diff_queued_diff; + struct diff_queue_struct outq = DIFF_QUEUE_INIT; + + if (!(o->output_format & + (DIFF_FORMAT_NAME | + DIFF_FORMAT_NAME_STATUS))) + return; + + for (int i = 0; i < q->nr; i++) { + struct diff_filepair *p = q->queue[i]; + if (ignore_match(p, o)) + diff_free_filepair(p); + else + diff_q(&outq, p); + } + + free(q->queue); + *q = outq; +}

And ignore_match(p, o) will run xdl_diff() for file pair p. This approach ensures that the behavior of `git diff --raw` and `git diff --check` remains unaffected.

Show 14 quoted lines
> I'm not sure if stuff like --stat would need something similar. It's
> already doing a content comparison, so presumably it handles it
> internally. Maybe stuff like --dirstat would need it, too? In which case
> we'd maybe want to annotate each filepair in an initial loop with
> whether it's modified at the content-level, and then take that into
> account in various code paths.
> 
> And of course it's horribly hacky looking. Some refactoring might help.
> Certainly it is silly to open /dev/null each time through the loop.
> There might also be a better way of checking whether the diff found
> anything than the found_changes flag.
> 
> So this is really just sketching out the direction, and somebody would
> need to figure out the details.

Seems like compute_diffstat() will run xdl_diff() to fill diffstat. Since diff_flush() calls compute_diffstat() for --stat, --dirstat=lines, --shortstat and --namestat, we shouldn’t run an extra xdl_diff() for them. I don’t know if --dirstat=files would need an extra xdl_diff() though.

Show 10 quoted lines
>> * Also, should we internally run diff twice, especially even when
>>   we are going to show the patch output and are not limited to
>>   FORMAT_NAME and FORMAT_NAME_STATUS?  Generally, running the real
>>   diff in any of the diffcore transformatin is a sign of trouble.
> 
> The patch above also runs the diff twice for "-Ifoo --name-only -p". But
> I think we are kind of stuck there. We want to show all name-only
> entries before any content diffs. So either we have to run the content
> diff twice, or we have to buffer it to show after we decide whether to
> show name-only entries.

I haven’t thought of a good way to avoid running the diff twice either. Caching the diff content seems quite complicated. Moreover, `git diff -G<regex> -p` requires running the diff twice: the first diff is used to filter out file pairs that don’t match, and the second diff outputs the patch.

On Tue, Jul 29, 2025 at 05:28:00PM -0700, Junio C Hamano wrote:
Show 10 quoted lines
> 
> The enthusiasm is appreciated, but the implementation raises two
> questions.
> 
> * This special cases -I<pattern>, but any option that causes us to
>   set the .diff_from_contents flag, not just -I<pattern>, can cause
>   the raw blob comparison to be potentially different from what the
>   blob contents are compared with various "ignore this class of
>   changes" criteria.  Shouldn't "git diff -w --name-status" and the
>   like get the same treatment?
Yes, I think I could modify ignore_match() to support -w and other ignore options.
Show 15 quoted lines
> Also, the usual way to compose a log message of this project is to
> 
>     - Give an observation on how the current system works in the
>       present tense (so no need to say "Currently X is Y", or
>       "Previously X was Y" to describe the state before your change;
>       just "X is Y" is enough), and discuss what you perceive as a
>       problem in it.
> 
>     - Propose a solution (optional---often, problem description
>       trivially leads to an obvious solution in reader's minds).
> 
>     - Give commands to somebody editing the codebase to "make it so",
>       instead of saying "This commit does X".
> 
> in this order.

Thank you once again for patiently explaining how to write proper log messages. I’ve made notes and am ready to apply them to future commits.

Thanks, Lidong

Previous: Jeff KingNext: Junio C Hamano
Message 16 of 35 in “git-diff: --ignore-matching-lines has no effect on the output when --name-only is used”
  1. hi@arnes.spaceJul 23, 2025
  2. Lidong YanJul 23, 2025
  3. Junio C HamanoJul 23, 2025
  4. Lidong YanJul 24, 2025
  5. Eric SunshineJul 24, 2025
  6. Lidong YanJul 24, 2025
  7. hi@arnes.spaceJul 25, 2025
  8. hi@arnes.spaceJul 25, 2025
  9. Lidong YanJul 25, 2025
  10. hi@arnes.spaceJul 25, 2025
  11. Jeff KingJul 25, 2025
  12. Junio C HamanoJul 25, 2025
  13. diff: ensure consistent diff behavior with -I<regex> across output formatsLidong Yan, Jul 29, 2025
  14. Junio C HamanoJul 30, 2025
  15. Jeff KingAug 2, 2025
  16. Lidong YanAug 3, 2025
  17. Junio C HamanoAug 3, 2025
  18. Junio C HamanoAug 4, 2025
  19. Jeff KingAug 4, 2025
  20. diff: ensure consistent diff behavior with -I<regex> across output formatsLidong Yan, Aug 3, 2025
  21. Junio C HamanoAug 4, 2025
  22. Lidong YanAug 4, 2025
  23. Junio C HamanoAug 4, 2025
  24. Lidong YanAug 5, 2025
  25. Junio C HamanoAug 5, 2025
  26. diff: ensure consistent diff behavior with ignore optionsLidong Yan, Aug 6, 2025
  27. Junio C HamanoAug 6, 2025
  28. Lidong YanAug 7, 2025
  29. Junio C HamanoAug 6, 2025
  30. Lidong YanAug 7, 2025
  31. diff: ensure consistent diff behavior with ignore optionsLidong Yan, Aug 7, 2025
  32. Junio C HamanoAug 7, 2025
  33. Lidong YanAug 8, 2025
  34. diff: ensure consistent diff behavior with ignore optionsLidong Yan, Aug 8, 2025
  35. Johannes SchindelinOct 16, 2025

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.