Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Documentation/config/diff.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,13 @@ endif::git-diff[]
`-l`. If not set, the default value is currently 1000. This
setting has no effect if rename detection is turned off.

`diff.renameThreshold`::
The minimum similarity threshold for rename detection;
equivalent to the `git diff` option `-M`. The value is a
percentage (e.g. `50%`), or a fraction between 0 and 1
(e.g. `0.5`). If not set, the default is 50%. This setting
has no effect if rename detection is turned off.

`diff.renames`::
Whether and how Git detects renames. If set to `false`,
rename detection is disabled. If set to `true`, basic rename
Expand Down
7 changes: 7 additions & 0 deletions Documentation/config/merge.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ include::fmt-merge-msg.adoc[]
currently defaults to 7000. This setting has no effect if
rename detection is turned off.

`merge.renameThreshold`::
The minimum similarity threshold for rename detection during
a merge. If not specified, defaults to the value of
`diff.renameThreshold`. See `diff.renameThreshold` for the
accepted value format. This setting has no effect if rename
detection is turned off.

`merge.renames`::
Whether Git detects renames. If set to `false`, rename detection
is disabled. If set to `true`, basic rename detection is enabled.
Expand Down
6 changes: 6 additions & 0 deletions Documentation/config/status.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ status.renameLimit::
in linkgit:git-status[1] and linkgit:git-commit[1]. Defaults to
the value of diff.renameLimit.

status.renameThreshold::
The minimum similarity threshold for rename detection in
linkgit:git-status[1] and linkgit:git-commit[1]. Defaults to
the value of diff.renameThreshold. See `diff.renameThreshold`
for the accepted value format.

status.renames::
Whether and how Git detects renames in linkgit:git-status[1] and
linkgit:git-commit[1] . If set to "false", rename detection is
Expand Down
16 changes: 16 additions & 0 deletions builtin/commit.c
Original file line number Diff line number Diff line change
Expand Up @@ -1672,6 +1672,22 @@ static int git_status_config(const char *k, const char *v,
s->detect_rename = git_config_rename(k, v);
return 0;
}
if (!strcmp(k, "diff.renamethreshold")) {
if (s->rename_score == -1) {
const char *arg = v;
if (!v)
return config_error_nonbool(k);
s->rename_score = parse_rename_score(&arg);
}
return 0;
}
if (!strcmp(k, "status.renamethreshold")) {
const char *arg = v;
if (!v)
return config_error_nonbool(k);
s->rename_score = parse_rename_score(&arg);
return 0;
}
return git_diff_ui_config(k, v, ctx, NULL);
}

Expand Down
11 changes: 11 additions & 0 deletions diff.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
static int diff_detect_rename_default;
static int diff_indent_heuristic = 1;
static int diff_rename_limit_default = 1000;
static int diff_rename_score_default;
static int diff_suppress_blank_empty;
static enum git_colorbool diff_use_color_default = GIT_COLOR_UNKNOWN;
static int diff_color_moved_default;
Expand Down Expand Up @@ -398,6 +399,15 @@ int git_diff_ui_config(const char *var, const char *value,
diff_detect_rename_default = git_config_rename(var, value);
return 0;
}
if (!strcmp(var, "diff.renamethreshold")) {
const char *arg = value;
if (!value)
return config_error_nonbool(var);
diff_rename_score_default = parse_rename_score(&arg);
if (*arg)
return error(_("invalid value for '%s': '%s'"), var, value);
return 0;
}
if (!strcmp(var, "diff.autorefreshindex")) {
diff_auto_refresh_index = git_config_bool(var, value);
return 0;
Expand Down Expand Up @@ -4856,6 +4866,7 @@ void repo_diff_setup(struct repository *r, struct diff_options *options)
options->add_remove = diff_addremove;
options->use_color = diff_use_color_default;
options->detect_rename = diff_detect_rename_default;
options->rename_score = diff_rename_score_default;
options->xdl_opts |= diff_algorithm;
if (diff_indent_heuristic)
DIFF_XDL_SET(options, INDENT_HEURISTIC);
Expand Down
10 changes: 10 additions & 0 deletions merge-ort.c
Original file line number Diff line number Diff line change
Expand Up @@ -5444,6 +5444,16 @@ static void merge_recursive_config(struct merge_options *opt, int ui)
repo_config_get_int(the_repository, "merge.verbosity", &opt->verbosity);
repo_config_get_int(the_repository, "diff.renamelimit", &opt->rename_limit);
repo_config_get_int(the_repository, "merge.renamelimit", &opt->rename_limit);
if (!repo_config_get_string(the_repository, "diff.renamethreshold", &value)) {
const char *arg = value;
opt->rename_score = parse_rename_score(&arg);
free(value);
}
if (!repo_config_get_string(the_repository, "merge.renamethreshold", &value)) {
const char *arg = value;
opt->rename_score = parse_rename_score(&arg);
free(value);
}
repo_config_get_bool(the_repository, "merge.renormalize", &renormalize);
opt->renormalize = renormalize;
if (!repo_config_get_string(the_repository, "diff.renames", &value)) {
Expand Down
25 changes: 25 additions & 0 deletions t/t4001-diff-rename.sh
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,21 @@ test_expect_success 'test diff.renames unset' '
compare_diff_patch current expected
'

test_expect_success 'diff.renameThreshold=100% suppresses inexact rename in diff' '
git -c diff.renameThreshold=100% diff --cached $tree >current &&
compare_diff_patch current no-rename
'

test_expect_success 'diff.renameThreshold=1% detects rename in diff' '
git -c diff.renameThreshold=1% diff --cached $tree >current &&
compare_diff_patch current expected
'

test_expect_success '-M overrides diff.renameThreshold' '
git -c diff.renameThreshold=100% diff -M --cached $tree >current &&
compare_diff_patch current expected
'

test_expect_success 'favour same basenames over different ones' '
cp path1 another-path &&
git add another-path &&
Expand Down Expand Up @@ -155,6 +170,16 @@ test_expect_success 'favour same basenames even with minor differences' '
test_grep "renamed: .*path1 -> subdir/path1" out
'

test_expect_success 'diff.renameThreshold with modified rename in status' '
git show HEAD:path1 | sed -e "s/Line 1/Changed 1/" \
-e "s/Line 2/Changed 2/" -e "s/Line 3/Changed 3/" >subdir/path1 &&
git add subdir/path1 &&
git -c diff.renameThreshold=100% status >out &&
test_grep ! "renamed:" out &&
git -c diff.renameThreshold=1% status >out &&
test_grep "renamed:" out
'

test_expect_success 'two files with same basename and same content' '
git reset --hard &&
mkdir -p dir/A dir/B &&
Expand Down
32 changes: 32 additions & 0 deletions t/t6434-merge-recursive-rename-options.sh
Original file line number Diff line number Diff line change
Expand Up @@ -332,4 +332,36 @@ test_expect_success 'merge.renames overrides diff.renames' '
$check_50
'

test_expect_success 'diff.renameThreshold sets merge threshold' '
git read-tree --reset -u HEAD &&
test_must_fail git -c diff.renameThreshold=$th0 merge-recursive $tail &&
check_threshold_0
'

test_expect_success 'diff.renameThreshold=100% limits to exact renames in merge' '
git read-tree --reset -u HEAD &&
test_must_fail git -c diff.renameThreshold=100% merge-recursive $tail &&
check_exact_renames
'

test_expect_success 'merge.renameThreshold overrides diff.renameThreshold' '
git read-tree --reset -u HEAD &&
test_must_fail git -c diff.renameThreshold=100% \
-c merge.renameThreshold=$th0 merge-recursive $tail &&
check_threshold_0
'

test_expect_success 'merge.renameThreshold defaults to diff.renameThreshold' '
git read-tree --reset -u HEAD &&
test_must_fail git -c diff.renameThreshold=$th2 merge-recursive $tail &&
check_threshold_2
'

test_expect_success '--find-renames overrides merge.renameThreshold' '
git read-tree --reset -u HEAD &&
test_must_fail git -c merge.renameThreshold=100% \
merge-recursive --find-renames=$th0 $tail &&
check_threshold_0
'

test_done
32 changes: 32 additions & 0 deletions t/t7525-status-rename.sh
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,38 @@ test_expect_success 'status score=01%' '
test_grep "renamed:" actual
'

test_expect_success 'diff.renameThreshold sets default threshold' '
git -c diff.renameThreshold=100% status >actual &&
test_grep "deleted:" actual &&
test_grep "new file:" actual
'

test_expect_success 'status.renameThreshold overrides diff.renameThreshold' '
git -c diff.renameThreshold=100% -c status.renameThreshold=01% status >actual &&
test_grep "renamed:" actual
'

test_expect_success 'diff.renameThreshold=01% detects rename in status' '
git -c diff.renameThreshold=01% status >actual &&
test_grep "renamed:" actual
'

test_expect_success 'commit honors diff.renameThreshold' '
git -c diff.renameThreshold=100% commit --dry-run >actual &&
test_grep "deleted:" actual &&
test_grep "new file:" actual
'

test_expect_success 'commit honors status.renameThreshold' '
git -c status.renameThreshold=01% commit --dry-run >actual &&
test_grep "renamed:" actual
'

test_expect_success '-M overrides status.renameThreshold' '
git -c status.renameThreshold=100% status -M=01% >actual &&
test_grep "renamed:" actual
'

test_expect_success 'copies not overridden by find-renames' '
cp renamed copy &&
git add copy &&
Expand Down
Loading