]> git.ipfire.org Git - thirdparty/git.git/commitdiff
blame: fix coloring for repeated suspects
authorRené Scharfe <l.s.r@web.de>
Sun, 1 Feb 2026 11:47:53 +0000 (12:47 +0100)
committerJunio C Hamano <gitster@pobox.com>
Mon, 2 Feb 2026 21:48:13 +0000 (13:48 -0800)
The option --ignore-rev passes the blame to an older commit.  This can
cause adjacent scoreboard entries to blame the same commit.  Currently
we only look at the present entry when determining whether a line needs
to be colored for --color-lines.  Check the previous entry as well.

Reported-by: Seth McDonald <sethmcmail@pm.me>
Signed-off-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/blame.c
t/t8012-blame-colors.sh

index 944952e30ebaac9066eedb91032ffbf1b302c434..4c946d2cf1eb082978291a643a896108b8ea4e40 100644 (file)
@@ -461,7 +461,8 @@ static void determine_line_heat(struct commit_info *ci, const char **dest_color)
        *dest_color = colorfield[i].col;
 }
 
-static void emit_other(struct blame_scoreboard *sb, struct blame_entry *ent, int opt)
+static void emit_other(struct blame_scoreboard *sb, struct blame_entry *ent,
+                      int opt, struct blame_entry *prev_ent)
 {
        int cnt;
        const char *cp;
@@ -492,7 +493,10 @@ static void emit_other(struct blame_scoreboard *sb, struct blame_entry *ent, int
                        the_hash_algo->hexsz : (size_t) abbrev;
 
                if (opt & OUTPUT_COLOR_LINE) {
-                       if (cnt > 0) {
+                       if (cnt > 0 ||
+                           (prev_ent &&
+                            oideq(&suspect->commit->object.oid,
+                                  &prev_ent->suspect->commit->object.oid))) {
                                color = repeated_meta_color;
                                reset = GIT_COLOR_RESET;
                        } else  {
@@ -578,7 +582,7 @@ static void emit_other(struct blame_scoreboard *sb, struct blame_entry *ent, int
 
 static void output(struct blame_scoreboard *sb, int option)
 {
-       struct blame_entry *ent;
+       struct blame_entry *ent, *prev_ent = NULL;
 
        if (option & OUTPUT_PORCELAIN) {
                for (ent = sb->ent; ent; ent = ent->next) {
@@ -600,7 +604,8 @@ static void output(struct blame_scoreboard *sb, int option)
                if (option & OUTPUT_PORCELAIN)
                        emit_porcelain(sb, ent, option);
                else {
-                       emit_other(sb, ent, option);
+                       emit_other(sb, ent, option, prev_ent);
+                       prev_ent = ent;
                }
        }
 }
index 3d77352650ffb6628f299469a04155cfa90b2ed2..5562eba43613ec997140c636add4341f4fac1ca1 100755 (executable)
@@ -28,6 +28,20 @@ test_expect_success 'colored blame colors contiguous lines' '
        test_line_count = 3 H.expect
 '
 
+test_expect_success 'color lines becoming contiguous due to --ignore-rev' '
+       mv hello.c hello.orig &&
+       sed "s/ /    /g" <hello.orig >hello.c &&
+       git add hello.c &&
+       git commit -m"tabs to spaces" &&
+       git -c color.blame.repeatedLines=yellow blame --color-lines --ignore-rev=HEAD hello.c >actual.raw &&
+       test_decode_color <actual.raw >actual &&
+       grep "<YELLOW>" <actual >darkened &&
+       grep "(F" darkened > F.expect &&
+       grep "(H" darkened > H.expect &&
+       test_line_count = 2 F.expect &&
+       test_line_count = 3 H.expect
+'
+
 test_expect_success 'color by age consistently colors old code' '
        git blame --color-by-age hello.c >actual.raw &&
        git -c blame.coloring=highlightRecent blame hello.c >actual.raw.2 &&