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

[PATCH 05/13] diff: don't use diff_options.use_color as a strict bool

From
Jeff King <peff@peff.net>
Date
Sep 16, 2025, 20:19 UTC
Message-ID
<20250916201933.GE612873@coredump.intra.peff.net>
In-Reply-To
<20250916201036.GA612463@coredump.intra.peff.net>

We disable --color-moved if color is not in use at all. This happens in diff_setup_done(), where we set options->color_moved to 0 if options->use_color is not true. But a strict boolean check here is not correct; use_color could be GIT_COLOR_UNKNOWN or GIT_COLOR_AUTO, both of which evaluate to true, even though we may later decide not to show colors.

We should be using want_color() to convert that git_colorbool into a true boolean. As it turns out, this does not produce wrong output. Even though we go to the trouble to detect the moved lines, ultimately we get the color values from diff_get_color(), which does check want_color(). And so it returns the empty string for each color, and we "color" the result with nothing.

So the output is correct, but there is a small but measurable performance cost to doing the line detection. E.g., in git.git before and after this patch (there are no colors shown because hyperfine redirects output to /dev/null):

  Benchmark 1: ./git.old log --no-merges -p --color-moved -1000
    Time (mean ± σ):      1.019 s ±  0.013 s    [User: 0.955 s, System: 0.064 s]
    Range (min … max):    1.005 s …  1.045 s    10 runs
  Benchmark 2: ./git.new log --no-merges -p --color-moved -1000
    Time (mean ± σ):     982.9 ms ±  14.5 ms    [User: 925.8 ms, System: 57.1 ms]
    Range (min … max):   965.1 ms … 1003.2 ms    10 runs
  Summary
    ./git.new log --no-merges -p --color-moved -1000 ran
      1.04 ± 0.02 times faster than ./git.old log --no-merges -p --color-moved -1000

Note that the fix is not quite as simple as just calling want_color() from diff_setup_done(). There's a subtle timing issue that goes back to daa0c3d971 (color: delay auto-color decision until point of use, 2011-08-17), the commit that adds want_color() in the first place. As discussed there, we must delay evaluating the colorbool value until all pager setup is complete.

So instead, we'll leave the "color_moved" field intact in diff_setup_done(), and modify the point where it is evaluated. Fortunately there is only one such spot that controls whether we run any of the color-moved code at all.

Signed-off-by: Jeff King <peff@peff.net>
---
 diff.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/diff.c b/diff.c
index e6c85c8491..cc3542e7f4 100644
--- a/diff.c
+++ b/diff.c
@@ -4995,8 +4995,7 @@ void diff_setup_done(struct diff_options *options)
 	if (options->flags.follow_renames)
 		diff_check_follow_pathspec(&options->pathspec, 1);
 
-	if (!options->use_color ||
-	    (options->flags.allow_external && external_diff()))
+	if (options->flags.allow_external && external_diff())
 		options->color_moved = 0;
 
 	if (options->filter_not) {
@@ -6733,7 +6732,7 @@ static void diff_flush_patch_all_file_pairs(struct diff_options *o)
 	if (WSEH_NEW & WS_RULE_MASK)
 		BUG("WS rules bit mask overlaps with diff symbol flags");
 
-	if (o->color_moved)
+	if (o->color_moved && want_color(o->use_color))
 		o->emitted_symbols = &esm;
 
 	if (o->additional_path_headers)
-- 
2.51.0.527.g34bc42dacd
Previous: Jeff KingNext: Jeff King
Message 7 of 18 in “unraveling the mysteries of color variables”
  1. 0/13 unraveling the mysteries of color variablesJeff King, Sep 16, 2025
  2. Jeff KingSep 16, 2025
  3. 01/13 color: use GIT_COLOR_* instead of numeric constantsJeff King, Sep 16, 2025
  4. 02/13 color: return enum from git_config_colorbool()Jeff King, Sep 16, 2025
  5. 03/13 grep: don't treat grep_opt.color as a strict boolJeff King, Sep 16, 2025
  6. 04/13 diff: simplify color_moved check when flushingJeff King, Sep 16, 2025
  7. 05/13 diff: don't use diff_options.use_color as a strict boolJeff King, Sep 16, 2025
  8. 06/13 diff: pass o->use_color directly to fill_metainfo()Jeff King, Sep 16, 2025
  9. 07/13 diff: stop passing ecbdata->use_color as booleanJeff King, Sep 16, 2025
  10. 08/13 pretty: use format_commit_context.auto_color as colorboolJeff King, Sep 16, 2025
  11. 09/13 color: use git_colorbool enum to type to store colorboolsJeff King, Sep 16, 2025
  12. 9/13 color: use git_colorbool enum type to store colorboolsJeff King, Sep 16, 2025
  13. 10/13 color: return bool from want_color()Jeff King, Sep 16, 2025
  14. 11/13 add-interactive: retain colorbool values longerJeff King, Sep 16, 2025
  15. 12/13 config: store want_color() result in a separate boolJeff King, Sep 16, 2025
  16. 13/13 color: convert git_colorbool into a structJeff King, Sep 16, 2025
  17. Junio C HamanoSep 16, 2025
  18. Jeff KingSep 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.