1
0
Fork 0
mirror of https://github.com/git/git.git synced 2024-05-12 12:56:08 +02:00

merge: add merge.renames config setting

Add the ability to control rename detection for merge via a config setting.
This setting behaves the same and defaults to the value of diff.renames but only
applies to merge.

Reviewed-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Helped-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Ben Peart <benpeart@microsoft.com>
Reviewed-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Ben Peart 2018-05-02 16:01:14 +00:00 committed by Junio C Hamano
parent a7152e9d22
commit 85b460305c
7 changed files with 64 additions and 12 deletions

View File

@ -38,6 +38,11 @@ merge.renameLimit::
diff.renameLimit. This setting has no effect if rename detection
is turned off.
merge.renames::
Whether and how Git detects renames. If set to "false",
rename detection is disabled. If set to "true", basic rename
detection is enabled. Defaults to the value of diff.renames.
merge.renormalize::
Tell Git that canonical representation of files in the
repository has changed over time (e.g. earlier commits record

View File

@ -23,8 +23,9 @@ recursive::
causing mismerges by tests done on actual merge commits
taken from Linux 2.6 kernel development history.
Additionally this can detect and handle merges involving
renames. This is the default merge strategy when
pulling or merging one branch.
renames, but currently cannot make use of detected
copies. This is the default merge strategy when pulling
or merging one branch.
+
The 'recursive' strategy can take the following options:
@ -84,12 +85,14 @@ no-renormalize;;
`merge.renormalize` configuration variable.
no-renames;;
Turn off rename detection.
Turn off rename detection. This overrides the `merge.renames`
configuration variable.
See also linkgit:git-diff[1] `--no-renames`.
find-renames[=<n>];;
Turn on rename detection, optionally setting the similarity
threshold. This is the default.
threshold. This is the default. This overrides the
'merge.renames' configuration variable.
See also linkgit:git-diff[1] `--find-renames`.
rename-threshold=<n>;;

2
diff.c
View File

@ -177,7 +177,7 @@ static int parse_submodule_params(struct diff_options *options, const char *valu
return 0;
}
static int git_config_rename(const char *var, const char *value)
int git_config_rename(const char *var, const char *value)
{
if (!value)
return DIFF_DETECT_RENAME;

1
diff.h
View File

@ -324,6 +324,7 @@ extern int git_diff_ui_config(const char *var, const char *value, void *cb);
extern void diff_setup(struct diff_options *);
extern int diff_opt_parse(struct diff_options *, const char **, int, const char *);
extern void diff_setup_done(struct diff_options *);
extern int git_config_rename(const char *var, const char *value);
#define DIFF_DETECT_RENAME 1
#define DIFF_DETECT_COPY 2

View File

@ -1603,7 +1603,15 @@ static struct diff_queue_struct *get_diffpairs(struct merge_options *o,
diff_setup(&opts);
opts.flags.recursive = 1;
opts.flags.rename_empty = 0;
opts.detect_rename = DIFF_DETECT_RENAME;
opts.detect_rename = merge_detect_rename(o);
/*
* We do not have logic to handle the detection of copies. In
* fact, it may not even make sense to add such logic: would we
* really want a change to a base file to be propagated through
* multiple other files by a merge?
*/
if (opts.detect_rename > DIFF_DETECT_RENAME)
opts.detect_rename = DIFF_DETECT_RENAME;
opts.rename_limit = o->merge_rename_limit >= 0 ? o->merge_rename_limit :
o->diff_rename_limit >= 0 ? o->diff_rename_limit :
1000;
@ -2643,7 +2651,7 @@ static int handle_renames(struct merge_options *o,
ri->head_renames = NULL;
ri->merge_renames = NULL;
if (!o->detect_rename)
if (!merge_detect_rename(o))
return 1;
head_pairs = get_diffpairs(o, common, head);
@ -3324,9 +3332,18 @@ int merge_recursive_generic(struct merge_options *o,
static void merge_recursive_config(struct merge_options *o)
{
char *value = NULL;
git_config_get_int("merge.verbosity", &o->verbosity);
git_config_get_int("diff.renamelimit", &o->diff_rename_limit);
git_config_get_int("merge.renamelimit", &o->merge_rename_limit);
if (!git_config_get_string("diff.renames", &value)) {
o->diff_detect_rename = git_config_rename("diff.renames", value);
free(value);
}
if (!git_config_get_string("merge.renames", &value)) {
o->merge_detect_rename = git_config_rename("merge.renames", value);
free(value);
}
git_config(git_xmerge_config, NULL);
}
@ -3339,7 +3356,8 @@ void init_merge_options(struct merge_options *o)
o->diff_rename_limit = -1;
o->merge_rename_limit = -1;
o->renormalize = 0;
o->detect_rename = 1;
o->diff_detect_rename = -1;
o->merge_detect_rename = -1;
merge_recursive_config(o);
merge_verbosity = getenv("GIT_MERGE_VERBOSITY");
if (merge_verbosity)
@ -3390,16 +3408,16 @@ int parse_merge_opt(struct merge_options *o, const char *s)
else if (!strcmp(s, "no-renormalize"))
o->renormalize = 0;
else if (!strcmp(s, "no-renames"))
o->detect_rename = 0;
o->merge_detect_rename = 0;
else if (!strcmp(s, "find-renames")) {
o->detect_rename = 1;
o->merge_detect_rename = 1;
o->rename_score = 0;
}
else if (skip_prefix(s, "find-renames=", &arg) ||
skip_prefix(s, "rename-threshold=", &arg)) {
if ((o->rename_score = parse_rename_score(&arg)) == -1 || *arg != 0)
return -1;
o->detect_rename = 1;
o->merge_detect_rename = 1;
}
else
return -1;

View File

@ -18,7 +18,8 @@ struct merge_options {
unsigned renormalize : 1;
long xdl_opts;
int verbosity;
int detect_rename;
int diff_detect_rename;
int merge_detect_rename;
int diff_rename_limit;
int merge_rename_limit;
int rename_score;
@ -57,6 +58,12 @@ struct collision_entry {
unsigned reported_already:1;
};
static inline int merge_detect_rename(struct merge_options *o)
{
return o->merge_detect_rename >= 0 ? o->merge_detect_rename :
o->diff_detect_rename >= 0 ? o->diff_detect_rename : 1;
}
/* merge_trees() but with recursive ancestor consolidation */
int merge_recursive(struct merge_options *o,
struct commit *h1,

View File

@ -309,4 +309,22 @@ test_expect_success 'last wins in --find-renames=<m> --rename-threshold=<n>' '
check_threshold_0
'
test_expect_success 'merge.renames disables rename detection' '
git read-tree --reset -u HEAD &&
git -c merge.renames=false merge-recursive $tail &&
check_no_renames
'
test_expect_success 'merge.renames defaults to diff.renames' '
git read-tree --reset -u HEAD &&
git -c diff.renames=false merge-recursive $tail &&
check_no_renames
'
test_expect_success 'merge.renames overrides diff.renames' '
git read-tree --reset -u HEAD &&
test_must_fail git -c diff.renames=false -c merge.renames=true merge-recursive $tail &&
$check_50
'
test_done