Skip to content

Commit 6e2ba77

Browse files
committed
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
2 parents c5aa4bc + 6f10a09 commit 6e2ba77

File tree

8 files changed

+69
-14
lines changed

8 files changed

+69
-14
lines changed

Documentation/diff-config.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,8 @@ diff.orderFile::
112112

113113
diff.renameLimit::
114114
The number of files to consider when performing the copy/rename
115-
detection; equivalent to the 'git diff' option `-l`.
115+
detection; equivalent to the 'git diff' option `-l`. This setting
116+
has no effect if rename detection is turned off.
116117

117118
diff.renames::
118119
Whether and how Git detects renames. If set to "false",

Documentation/merge-config.txt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,13 @@ include::fmt-merge-msg-config.txt[]
3535
merge.renameLimit::
3636
The number of files to consider when performing rename detection
3737
during a merge; if not specified, defaults to the value of
38-
diff.renameLimit.
38+
diff.renameLimit. This setting has no effect if rename detection
39+
is turned off.
40+
41+
merge.renames::
42+
Whether and how Git detects renames. If set to "false",
43+
rename detection is disabled. If set to "true", basic rename
44+
detection is enabled. Defaults to the value of diff.renames.
3945

4046
merge.renormalize::
4147
Tell Git that canonical representation of files in the

Documentation/merge-strategies.txt

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,9 @@ recursive::
2323
causing mismerges by tests done on actual merge commits
2424
taken from Linux 2.6 kernel development history.
2525
Additionally this can detect and handle merges involving
26-
renames. This is the default merge strategy when
27-
pulling or merging one branch.
26+
renames, but currently cannot make use of detected
27+
copies. This is the default merge strategy when pulling
28+
or merging one branch.
2829
+
2930
The 'recursive' strategy can take the following options:
3031

@@ -84,12 +85,14 @@ no-renormalize;;
8485
`merge.renormalize` configuration variable.
8586

8687
no-renames;;
87-
Turn off rename detection.
88+
Turn off rename detection. This overrides the `merge.renames`
89+
configuration variable.
8890
See also linkgit:git-diff[1] `--no-renames`.
8991

9092
find-renames[=<n>];;
9193
Turn on rename detection, optionally setting the similarity
92-
threshold. This is the default.
94+
threshold. This is the default. This overrides the
95+
'merge.renames' configuration variable.
9396
See also linkgit:git-diff[1] `--find-renames`.
9497

9598
rename-threshold=<n>;;

diff.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ static int parse_submodule_params(struct diff_options *options, const char *valu
177177
return 0;
178178
}
179179

180-
static int git_config_rename(const char *var, const char *value)
180+
int git_config_rename(const char *var, const char *value)
181181
{
182182
if (!value)
183183
return DIFF_DETECT_RENAME;

diff.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,7 @@ extern int git_diff_ui_config(const char *var, const char *value, void *cb);
324324
extern void diff_setup(struct diff_options *);
325325
extern int diff_opt_parse(struct diff_options *, const char **, int, const char *);
326326
extern void diff_setup_done(struct diff_options *);
327+
extern int git_config_rename(const char *var, const char *value);
327328

328329
#define DIFF_DETECT_RENAME 1
329330
#define DIFF_DETECT_COPY 2

merge-recursive.c

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,7 @@ static int git_merge_trees(struct merge_options *o,
356356
o->unpack_opts.fn = threeway_merge;
357357
o->unpack_opts.src_index = &the_index;
358358
o->unpack_opts.dst_index = &tmp_index;
359+
o->unpack_opts.aggressive = !merge_detect_rename(o);
359360
setup_unpack_trees_porcelain(&o->unpack_opts, "merge");
360361

361362
init_tree_desc_from_tree(t+0, common);
@@ -1603,7 +1604,15 @@ static struct diff_queue_struct *get_diffpairs(struct merge_options *o,
16031604
diff_setup(&opts);
16041605
opts.flags.recursive = 1;
16051606
opts.flags.rename_empty = 0;
1606-
opts.detect_rename = DIFF_DETECT_RENAME;
1607+
opts.detect_rename = merge_detect_rename(o);
1608+
/*
1609+
* We do not have logic to handle the detection of copies. In
1610+
* fact, it may not even make sense to add such logic: would we
1611+
* really want a change to a base file to be propagated through
1612+
* multiple other files by a merge?
1613+
*/
1614+
if (opts.detect_rename > DIFF_DETECT_RENAME)
1615+
opts.detect_rename = DIFF_DETECT_RENAME;
16071616
opts.rename_limit = o->merge_rename_limit >= 0 ? o->merge_rename_limit :
16081617
o->diff_rename_limit >= 0 ? o->diff_rename_limit :
16091618
1000;
@@ -2643,7 +2652,7 @@ static int handle_renames(struct merge_options *o,
26432652
ri->head_renames = NULL;
26442653
ri->merge_renames = NULL;
26452654

2646-
if (!o->detect_rename)
2655+
if (!merge_detect_rename(o))
26472656
return 1;
26482657

26492658
head_pairs = get_diffpairs(o, common, head);
@@ -3325,9 +3334,18 @@ int merge_recursive_generic(struct merge_options *o,
33253334

33263335
static void merge_recursive_config(struct merge_options *o)
33273336
{
3337+
char *value = NULL;
33283338
git_config_get_int("merge.verbosity", &o->verbosity);
33293339
git_config_get_int("diff.renamelimit", &o->diff_rename_limit);
33303340
git_config_get_int("merge.renamelimit", &o->merge_rename_limit);
3341+
if (!git_config_get_string("diff.renames", &value)) {
3342+
o->diff_detect_rename = git_config_rename("diff.renames", value);
3343+
free(value);
3344+
}
3345+
if (!git_config_get_string("merge.renames", &value)) {
3346+
o->merge_detect_rename = git_config_rename("merge.renames", value);
3347+
free(value);
3348+
}
33313349
git_config(git_xmerge_config, NULL);
33323350
}
33333351

@@ -3340,7 +3358,8 @@ void init_merge_options(struct merge_options *o)
33403358
o->diff_rename_limit = -1;
33413359
o->merge_rename_limit = -1;
33423360
o->renormalize = 0;
3343-
o->detect_rename = 1;
3361+
o->diff_detect_rename = -1;
3362+
o->merge_detect_rename = -1;
33443363
merge_recursive_config(o);
33453364
merge_verbosity = getenv("GIT_MERGE_VERBOSITY");
33463365
if (merge_verbosity)
@@ -3391,16 +3410,16 @@ int parse_merge_opt(struct merge_options *o, const char *s)
33913410
else if (!strcmp(s, "no-renormalize"))
33923411
o->renormalize = 0;
33933412
else if (!strcmp(s, "no-renames"))
3394-
o->detect_rename = 0;
3413+
o->merge_detect_rename = 0;
33953414
else if (!strcmp(s, "find-renames")) {
3396-
o->detect_rename = 1;
3415+
o->merge_detect_rename = 1;
33973416
o->rename_score = 0;
33983417
}
33993418
else if (skip_prefix(s, "find-renames=", &arg) ||
34003419
skip_prefix(s, "rename-threshold=", &arg)) {
34013420
if ((o->rename_score = parse_rename_score(&arg)) == -1 || *arg != 0)
34023421
return -1;
3403-
o->detect_rename = 1;
3422+
o->merge_detect_rename = 1;
34043423
}
34053424
else
34063425
return -1;

merge-recursive.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ struct merge_options {
1818
unsigned renormalize : 1;
1919
long xdl_opts;
2020
int verbosity;
21-
int detect_rename;
21+
int diff_detect_rename;
22+
int merge_detect_rename;
2223
int diff_rename_limit;
2324
int merge_rename_limit;
2425
int rename_score;
@@ -57,6 +58,12 @@ struct collision_entry {
5758
unsigned reported_already:1;
5859
};
5960

61+
static inline int merge_detect_rename(struct merge_options *o)
62+
{
63+
return o->merge_detect_rename >= 0 ? o->merge_detect_rename :
64+
o->diff_detect_rename >= 0 ? o->diff_detect_rename : 1;
65+
}
66+
6067
/* merge_trees() but with recursive ancestor consolidation */
6168
int merge_recursive(struct merge_options *o,
6269
struct commit *h1,

t/t3034-merge-recursive-rename-options.sh

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,4 +309,22 @@ test_expect_success 'last wins in --find-renames=<m> --rename-threshold=<n>' '
309309
check_threshold_0
310310
'
311311

312+
test_expect_success 'merge.renames disables rename detection' '
313+
git read-tree --reset -u HEAD &&
314+
git -c merge.renames=false merge-recursive $tail &&
315+
check_no_renames
316+
'
317+
318+
test_expect_success 'merge.renames defaults to diff.renames' '
319+
git read-tree --reset -u HEAD &&
320+
git -c diff.renames=false merge-recursive $tail &&
321+
check_no_renames
322+
'
323+
324+
test_expect_success 'merge.renames overrides diff.renames' '
325+
git read-tree --reset -u HEAD &&
326+
test_must_fail git -c diff.renames=false -c merge.renames=true merge-recursive $tail &&
327+
$check_50
328+
'
329+
312330
test_done

0 commit comments

Comments
 (0)