Skip to content
Snippets Groups Projects
Commit 6e2ba77b authored by Junio C Hamano's avatar Junio C Hamano
Browse files

Merge branch 'bp/merge-rename-config'

With merge.renames configuration set to false, the recursive merge
strategy can be told not to spend cycles trying to find renamed
paths and merge them accordingly.

* bp/merge-rename-config:
  merge: pass aggressive when rename detection is turned off
  merge: add merge.renames config setting
  merge: update documentation for {merge,diff}.renameLimit
parents c5aa4bcc 6f10a09e
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -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",
Loading
Loading
Loading
Loading
@@ -35,7 +35,13 @@ 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.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
Loading
Loading
Loading
Loading
@@ -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:
 
Loading
Loading
@@ -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>;;
Loading
Loading
Loading
Loading
@@ -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;
Loading
Loading
Loading
Loading
@@ -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
Loading
Loading
Loading
Loading
@@ -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);
Loading
Loading
@@ -1603,7 +1604,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;
Loading
Loading
@@ -2643,7 +2652,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);
Loading
Loading
@@ -3325,9 +3334,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);
}
 
Loading
Loading
@@ -3340,7 +3358,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)
Loading
Loading
@@ -3391,16 +3410,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;
Loading
Loading
Loading
Loading
@@ -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;
Loading
Loading
@@ -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,
Loading
Loading
Loading
Loading
@@ -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
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment