aboutsummaryrefslogtreecommitdiffstats
path: root/t/t8015-blame-diff-algorithm.sh
diff options
context:
space:
mode:
authorAntonin Delpeuch <antonin@delpeuch.eu>2025-11-06 22:41:54 +0000
committerJunio C Hamano <gitster@pobox.com>2025-11-07 07:32:52 -0800
commitbed7812b6a6366f302590ef9e7d9dcb5a3b787f0 (patch)
tree3f3f35426eaed6fe3d43eae285956984553ec6b9 /t/t8015-blame-diff-algorithm.sh
parentxdiff: add 'minimal' to XDF_DIFF_ALGORITHM_MASK (diff)
downloadgit-bed7812b6a6366f302590ef9e7d9dcb5a3b787f0.tar.gz
git-bed7812b6a6366f302590ef9e7d9dcb5a3b787f0.zip
blame: make diff algorithm configurable
The diff algorithm used in 'git-blame(1)' is set to 'myers', without the possibility to change it aside from the `--minimal` option. There has been long-standing interest in changing the default diff algorithm to "histogram", and Git 3.0 was floated as a possible occasion for taking some steps towards that: https://lore.kernel.org/git/xmqqed873vgn.fsf@gitster.g/ As a preparation for this move, it is worth making sure that the diff algorithm is configurable where useful. Make it configurable in the `git-blame(1)` command by introducing the `--diff-algorithm` option and make honor the `diff.algorithm` config variable. Keep Myers diff as the default. Signed-off-by: Antonin Delpeuch <antonin@delpeuch.eu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 't/t8015-blame-diff-algorithm.sh')
-rwxr-xr-xt/t8015-blame-diff-algorithm.sh203
1 files changed, 203 insertions, 0 deletions
diff --git a/t/t8015-blame-diff-algorithm.sh b/t/t8015-blame-diff-algorithm.sh
new file mode 100755
index 0000000000..55e1d540dc
--- /dev/null
+++ b/t/t8015-blame-diff-algorithm.sh
@@ -0,0 +1,203 @@
+#!/bin/sh
+
+test_description='git blame with specific diff algorithm'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+ cat >file.c <<-\EOF &&
+ int f(int x, int y)
+ {
+ if (x == 0)
+ {
+ return y;
+ }
+ return x;
+ }
+
+ int g(size_t u)
+ {
+ while (u < 30)
+ {
+ u++;
+ }
+ return u;
+ }
+ EOF
+ test_write_lines x x x x >file.txt &&
+ git add file.c file.txt &&
+ GIT_AUTHOR_NAME=Commit_1 git commit -m Commit_1 &&
+
+ cat >file.c <<-\EOF &&
+ int g(size_t u)
+ {
+ while (u < 30)
+ {
+ u++;
+ }
+ return u;
+ }
+
+ int h(int x, int y, int z)
+ {
+ if (z == 0)
+ {
+ return x;
+ }
+ return y;
+ }
+ EOF
+ test_write_lines x x x A B C D x E F G >file.txt &&
+ git add file.c file.txt &&
+ GIT_AUTHOR_NAME=Commit_2 git commit -m Commit_2
+'
+
+test_expect_success 'blame uses Myers diff algorithm by default' '
+ cat >expected <<-\EOF &&
+ Commit_2 int g(size_t u)
+ Commit_1 {
+ Commit_2 while (u < 30)
+ Commit_1 {
+ Commit_2 u++;
+ Commit_1 }
+ Commit_2 return u;
+ Commit_1 }
+ Commit_1
+ Commit_2 int h(int x, int y, int z)
+ Commit_1 {
+ Commit_2 if (z == 0)
+ Commit_1 {
+ Commit_2 return x;
+ Commit_1 }
+ Commit_2 return y;
+ Commit_1 }
+ EOF
+
+ git blame file.c > output &&
+ sed -e "s/^[^ ]* (\([^ ]*\) [^)]*)/\1/g" output > without_varying_parts &&
+ sed -e "s/ *$//g" without_varying_parts > actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'blame honors --diff-algorithm option' '
+ cat >expected <<-\EOF &&
+ Commit_1 int g(size_t u)
+ Commit_1 {
+ Commit_1 while (u < 30)
+ Commit_1 {
+ Commit_1 u++;
+ Commit_1 }
+ Commit_1 return u;
+ Commit_1 }
+ Commit_2
+ Commit_2 int h(int x, int y, int z)
+ Commit_2 {
+ Commit_2 if (z == 0)
+ Commit_2 {
+ Commit_2 return x;
+ Commit_2 }
+ Commit_2 return y;
+ Commit_2 }
+ EOF
+
+ git blame file.c --diff-algorithm histogram > output &&
+ sed -e "s/^[^ ]* (\([^ ]*\) [^)]*)/\1/g" output > without_varying_parts &&
+ sed -e "s/ *$//g" without_varying_parts > actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'blame honors diff.algorithm config variable' '
+ cat >expected <<-\EOF &&
+ Commit_1 int g(size_t u)
+ Commit_1 {
+ Commit_1 while (u < 30)
+ Commit_1 {
+ Commit_1 u++;
+ Commit_1 }
+ Commit_1 return u;
+ Commit_1 }
+ Commit_2
+ Commit_2 int h(int x, int y, int z)
+ Commit_2 {
+ Commit_2 if (z == 0)
+ Commit_2 {
+ Commit_2 return x;
+ Commit_2 }
+ Commit_2 return y;
+ Commit_2 }
+ EOF
+
+ git -c diff.algorithm=histogram blame file.c > output &&
+ sed -e "s/^[^ ]* (\([^ ]*\) [^)]*)/\1/g" \
+ -e "s/ *$//g" output > actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'blame gives priority to --diff-algorithm over diff.algorithm' '
+ cat >expected <<-\EOF &&
+ Commit_1 int g(size_t u)
+ Commit_1 {
+ Commit_1 while (u < 30)
+ Commit_1 {
+ Commit_1 u++;
+ Commit_1 }
+ Commit_1 return u;
+ Commit_1 }
+ Commit_2
+ Commit_2 int h(int x, int y, int z)
+ Commit_2 {
+ Commit_2 if (z == 0)
+ Commit_2 {
+ Commit_2 return x;
+ Commit_2 }
+ Commit_2 return y;
+ Commit_2 }
+ EOF
+
+ git -c diff.algorithm=myers blame file.c --diff-algorithm histogram > output &&
+ sed -e "s/^[^ ]* (\([^ ]*\) [^)]*)/\1/g" \
+ -e "s/ *$//g" output > actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'blame honors --minimal option' '
+ cat >expected <<-\EOF &&
+ Commit_1 x
+ Commit_1 x
+ Commit_1 x
+ Commit_2 A
+ Commit_2 B
+ Commit_2 C
+ Commit_2 D
+ Commit_1 x
+ Commit_2 E
+ Commit_2 F
+ Commit_2 G
+ EOF
+
+ git blame file.txt --minimal > output &&
+ sed -e "s/^[^ ]* (\([^ ]*\) [^)]*)/\1/g" output > actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'blame respects the order of diff options' '
+ cat >expected <<-\EOF &&
+ Commit_1 x
+ Commit_1 x
+ Commit_1 x
+ Commit_2 A
+ Commit_2 B
+ Commit_2 C
+ Commit_2 D
+ Commit_2 x
+ Commit_2 E
+ Commit_2 F
+ Commit_2 G
+ EOF
+
+ git blame file.txt --minimal --diff-algorithm myers > output &&
+ sed -e "s/^[^ ]* (\([^ ]*\) [^)]*)/\1/g" output > actual &&
+ test_cmp expected actual
+'
+
+test_done