From a7152e9d226652e6ceaa64f099fc628aa2a909bd Mon Sep 17 00:00:00 2001 From: Ben Peart Date: Wed, 2 May 2018 16:01:13 +0000 Subject: merge: update documentation for {merge,diff}.renameLimit Update the documentation to better indicate that the renameLimit setting is ignored if rename detection is turned off via command line options or config settings. Signed-off-by: Ben Peart Reviewed-by: Elijah Newren Signed-off-by: Junio C Hamano diff --git a/Documentation/diff-config.txt b/Documentation/diff-config.txt index 5ca942a..77caa66 100644 --- a/Documentation/diff-config.txt +++ b/Documentation/diff-config.txt @@ -112,7 +112,8 @@ diff.orderFile:: diff.renameLimit:: The number of files to consider when performing the copy/rename - detection; equivalent to the 'git diff' option `-l`. + detection; equivalent to the 'git diff' option `-l`. This setting + has no effect if rename detection is turned off. diff.renames:: Whether and how Git detects renames. If set to "false", diff --git a/Documentation/merge-config.txt b/Documentation/merge-config.txt index 12b6bbf..48ee3bc 100644 --- a/Documentation/merge-config.txt +++ b/Documentation/merge-config.txt @@ -35,7 +35,8 @@ include::fmt-merge-msg-config.txt[] merge.renameLimit:: The number of files to consider when performing rename detection during a merge; if not specified, defaults to the value of - diff.renameLimit. + diff.renameLimit. This setting has no effect if rename detection + is turned off. merge.renormalize:: Tell Git that canonical representation of files in the -- cgit v0.10.2-6-g49f6 From 85b460305ce7ed399c83499851f46c4f870ce280 Mon Sep 17 00:00:00 2001 From: Ben Peart Date: Wed, 2 May 2018 16:01:14 +0000 Subject: 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 Helped-by: Elijah Newren Signed-off-by: Ben Peart Reviewed-by: Elijah Newren Signed-off-by: Junio C Hamano diff --git a/Documentation/merge-config.txt b/Documentation/merge-config.txt index 48ee3bc..662c271 100644 --- a/Documentation/merge-config.txt +++ b/Documentation/merge-config.txt @@ -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 diff --git a/Documentation/merge-strategies.txt b/Documentation/merge-strategies.txt index 4a58aad..aa66cbe 100644 --- a/Documentation/merge-strategies.txt +++ b/Documentation/merge-strategies.txt @@ -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[=];; 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=;; diff --git a/diff.c b/diff.c index 1289df4..5dfc24a 100644 --- a/diff.c +++ b/diff.c @@ -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; diff --git a/diff.h b/diff.h index d29560f..dedac47 100644 --- a/diff.h +++ b/diff.h @@ -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 diff --git a/merge-recursive.c b/merge-recursive.c index 13b4762..e984049 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -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; diff --git a/merge-recursive.h b/merge-recursive.h index 248093e..fa7bc6b 100644 --- a/merge-recursive.h +++ b/merge-recursive.h @@ -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, diff --git a/t/t3034-merge-recursive-rename-options.sh b/t/t3034-merge-recursive-rename-options.sh index b9c4028..3d9fae6 100755 --- a/t/t3034-merge-recursive-rename-options.sh +++ b/t/t3034-merge-recursive-rename-options.sh @@ -309,4 +309,22 @@ test_expect_success 'last wins in --find-renames= --rename-threshold=' ' 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 -- cgit v0.10.2-6-g49f6 From 6f10a09e0a1a7c3c3a6ee8e67390a4839dbe6a1b Mon Sep 17 00:00:00 2001 From: Ben Peart Date: Wed, 2 May 2018 16:01:16 +0000 Subject: merge: pass aggressive when rename detection is turned off Set aggressive flag in git_merge_trees() when rename detection is turned off. This allows read_tree() to auto resolve more cases that would have otherwise been handled by the rename detection. Reviewed-by: Johannes Schindelin Signed-off-by: Ben Peart Reviewed-by: Elijah Newren Signed-off-by: Junio C Hamano diff --git a/merge-recursive.c b/merge-recursive.c index e984049..680e012 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -356,6 +356,7 @@ static int git_merge_trees(struct merge_options *o, o->unpack_opts.fn = threeway_merge; o->unpack_opts.src_index = &the_index; o->unpack_opts.dst_index = &tmp_index; + o->unpack_opts.aggressive = !merge_detect_rename(o); setup_unpack_trees_porcelain(&o->unpack_opts, "merge"); init_tree_desc_from_tree(t+0, common); -- cgit v0.10.2-6-g49f6