Skip to content

Commit 32b59d0

Browse files
committed
blame: make diff algorithm configurable
The diff algorithm used in 'git-blame(1)' can be configured using the `--diff-algorithm` option or the `diff.algorithm` config variable. Myers diff remains the default. Signed-off-by: Antonin Delpeuch <antonin@delpeuch.eu>
1 parent 4253630 commit 32b59d0

2 files changed

Lines changed: 58 additions & 1 deletion

File tree

Documentation/git-blame.adoc

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,27 @@ include::blame-options.adoc[]
8585
Ignore whitespace when comparing the parent's version and
8686
the child's to find where the lines came from.
8787

88+
`--diff-algorithm=(patience|minimal|histogram|myers)`::
89+
Choose a diff algorithm. The variants are as follows:
90+
+
91+
--
92+
`default`;;
93+
`myers`;;
94+
The basic greedy diff algorithm. Currently, this is the default.
95+
`minimal`;;
96+
Spend extra time to make sure the smallest possible diff is
97+
produced.
98+
`patience`;;
99+
Use "patience diff" algorithm when generating patches.
100+
`histogram`;;
101+
This algorithm extends the patience algorithm to "support
102+
low-occurrence common elements".
103+
--
104+
+
105+
For instance, if you configured the `diff.algorithm` variable to a
106+
non-default value and want to use the default one, then you
107+
have to use `--diff-algorithm=default` option.
108+
88109
--abbrev=<n>::
89110
Instead of using the default 7+1 hexadecimal digits as the
90111
abbreviated object name, use <m>+1 digits, where <m> is at

builtin/blame.c

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -779,6 +779,19 @@ static int git_blame_config(const char *var, const char *value,
779779
}
780780
}
781781

782+
if (!strcmp(var, "diff.algorithm")) {
783+
long diff_algorithm;
784+
if (!value)
785+
return config_error_nonbool(var);
786+
diff_algorithm = parse_algorithm_value(value);
787+
if (diff_algorithm < 0)
788+
return error(_("unknown value for config '%s': %s"),
789+
var, value);
790+
xdl_opts &= ~XDF_DIFF_ALGORITHM_MASK;
791+
xdl_opts |= diff_algorithm;
792+
return 0;
793+
}
794+
782795
if (git_diff_heuristic_config(var, value, cb) < 0)
783796
return -1;
784797
if (userdiff_config(var, value) < 0)
@@ -824,6 +837,26 @@ static int blame_move_callback(const struct option *option, const char *arg, int
824837
return 0;
825838
}
826839

840+
static int blame_diff_algorithm_callback(const struct option *option,
841+
const char *arg, int unset)
842+
{
843+
int *opt = option->value;
844+
long value = parse_algorithm_value(arg);
845+
846+
BUG_ON_OPT_NEG(unset);
847+
848+
if (value < 0)
849+
return error(_("option diff-algorithm accepts \"myers\", "
850+
"\"minimal\", \"patience\" and \"histogram\""));
851+
852+
// ignore any previous --minimal setting, following git-diff's behavior
853+
*opt &= ~XDF_NEED_MINIMAL;
854+
*opt &= ~XDF_DIFF_ALGORITHM_MASK;
855+
*opt |= value;
856+
857+
return 0;
858+
}
859+
827860
static int is_a_rev(const char *name)
828861
{
829862
struct object_id oid;
@@ -908,13 +941,16 @@ int cmd_blame(int argc,
908941
OPT_BIT('f', "show-name", &output_option, N_("show original filename (Default: auto)"), OUTPUT_SHOW_NAME),
909942
OPT_BIT('n', "show-number", &output_option, N_("show original linenumber (Default: off)"), OUTPUT_SHOW_NUMBER),
910943
OPT_BIT('p', "porcelain", &output_option, N_("show in a format designed for machine consumption"), OUTPUT_PORCELAIN),
911-
OPT_BIT(0, "line-porcelain", &output_option, N_("show porcelain format with per-line commit information"), OUTPUT_PORCELAIN|OUTPUT_LINE_PORCELAIN),
944+
OPT_BIT(0, "line-porcelain", &output_option, N_("show porcelain format with per-line commit information"), OUTPUT_PORCELAIN | OUTPUT_LINE_PORCELAIN),
912945
OPT_BIT('c', NULL, &output_option, N_("use the same output mode as git-annotate (Default: off)"), OUTPUT_ANNOTATE_COMPAT),
913946
OPT_BIT('t', NULL, &output_option, N_("show raw timestamp (Default: off)"), OUTPUT_RAW_TIMESTAMP),
914947
OPT_BIT('l', NULL, &output_option, N_("show long commit SHA1 (Default: off)"), OUTPUT_LONG_OBJECT_NAME),
915948
OPT_BIT('s', NULL, &output_option, N_("suppress author name and timestamp (Default: off)"), OUTPUT_NO_AUTHOR),
916949
OPT_BIT('e', "show-email", &output_option, N_("show author email instead of name (Default: off)"), OUTPUT_SHOW_EMAIL),
917950
OPT_BIT('w', NULL, &xdl_opts, N_("ignore whitespace differences"), XDF_IGNORE_WHITESPACE),
951+
OPT_CALLBACK_F(0, "diff-algorithm", &xdl_opts, N_("<algorithm>"),
952+
N_("choose a diff algorithm"),
953+
PARSE_OPT_NONEG, blame_diff_algorithm_callback),
918954
OPT_STRING_LIST(0, "ignore-rev", &ignore_rev_list, N_("rev"), N_("ignore <rev> when blaming")),
919955
OPT_STRING_LIST(0, "ignore-revs-file", &ignore_revs_file_list, N_("file"), N_("ignore revisions from <file>")),
920956
OPT_BIT(0, "color-lines", &output_option, N_("color redundant metadata from previous line differently"), OUTPUT_COLOR_LINE),

0 commit comments

Comments
 (0)