git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v4 2/3] merge: Add merge.renames config setting

From
Ben Peart <ben.peart@microsoft.com>
Date
May 2, 2018, 16:01 UTC
Message-ID
<20180502160056.5836-3-benpeart@microsoft.com>
In-Reply-To
<20180502160056.5836-1-benpeart@microsoft.com>

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>
---
 Documentation/merge-config.txt            |  5 ++++
 Documentation/merge-strategies.txt        | 11 ++++++---
 diff.c                                    |  2 +-
 diff.h                                    |  1 +
 merge-recursive.c                         | 30 ++++++++++++++++++-----
 merge-recursive.h                         |  8 +++++-
 t/t3034-merge-recursive-rename-options.sh | 18 ++++++++++++++
 7 files changed, 63 insertions(+), 12 deletions(-)
diff --git a/Documentation/merge-config.txt b/Documentation/merge-config.txt
index 48ee3bce77..662c2713ca 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 fd5d748d1b..30acc99232 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[=<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>;;
diff --git a/diff.c b/diff.c
index fb22b19f09..e744b35cdc 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 7cf276f077..966fc8fce6 100644
--- a/diff.h
+++ b/diff.h
@@ -321,6 +321,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 5f42c677d5..372ffbbacc 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -1524,7 +1524,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;
@@ -2564,7 +2572,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);
@@ -3241,9 +3249,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);
 }
 
@@ -3256,7 +3273,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)
@@ -3307,16 +3325,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 d863cf8867..c1d9b5b3d9 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;
@@ -55,6 +56,11 @@ struct collision_entry {
 	struct string_list source_files;
 	unsigned reported_already:1;
 };
+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,
diff --git a/t/t3034-merge-recursive-rename-options.sh b/t/t3034-merge-recursive-rename-options.sh
index b9c4028496..3d9fae68c4 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=<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
-- 
2.17.0.windows.1
Previous: Ben PeartNext: Junio C Hamano
Message 62 of 65 in “add additional config settings for merge”
  1. 0/2 add additional config settings for mergeBen Peart, Apr 20, 2018
  2. 1/2 merge: Add merge.renames config settingBen Peart, Apr 20, 2018
  3. Elijah NewrenApr 20, 2018
  4. Elijah NewrenApr 20, 2018
  5. Ben PeartApr 23, 2018
  6. Ben PeartApr 20, 2018
  7. Elijah NewrenApr 20, 2018
  8. Junio C HamanoApr 21, 2018
  9. Ben PeartApr 23, 2018
  10. Junio C HamanoApr 23, 2018
  11. Johannes SchindelinApr 24, 2018
  12. Elijah NewrenApr 24, 2018
  13. Johannes SchindelinApr 25, 2018
  14. Eckhard MaaßApr 22, 2018
  15. Ben PeartApr 23, 2018
  16. Eckhard MaaßApr 23, 2018
  17. Ben PeartApr 24, 2018
  18. Ben PeartApr 23, 2018
  19. 2/2 merge: Add merge.aggressive config settingBen Peart, Apr 20, 2018
  20. Elijah NewrenApr 20, 2018
  21. Ben PeartApr 24, 2018
  22. Elijah NewrenApr 24, 2018
  23. Junio C HamanoApr 24, 2018
  24. Ben PeartApr 25, 2018
  25. Elijah NewrenApr 20, 2018
  26. Ben PeartApr 20, 2018
  27. 0/2 add additional config settings for mergeBen Peart, Apr 24, 2018
  28. 1/2 merge: Add merge.renames config settingBen Peart, Apr 24, 2018
  29. Elijah NewrenApr 24, 2018
  30. Elijah NewrenApr 24, 2018
  31. Ben PeartApr 24, 2018
  32. Elijah NewrenApr 25, 2018
  33. 2/2 merge: Add merge.aggressive config settingBen Peart, Apr 24, 2018
  34. Junio C HamanoApr 25, 2018
  35. Ben PeartApr 25, 2018
  36. Junio C HamanoApr 26, 2018
  37. 0/3 add merge.renames config settingBen Peart, Apr 26, 2018
  38. 1/3 merge: update documentation for {merge,diff}.renameLimitBen Peart, Apr 26, 2018
  39. Elijah NewrenApr 26, 2018
  40. Jonathan TanApr 26, 2018
  41. 2/3 merge: Add merge.renames config settingBen Peart, Apr 26, 2018
  42. Elijah NewrenApr 26, 2018
  43. Ben PeartApr 27, 2018
  44. Junio C HamanoApr 27, 2018
  45. Elijah NewrenApr 27, 2018
  46. Johannes SchindelinApr 27, 2018
  47. Elijah NewrenApr 27, 2018
  48. Eckhard MaaßApr 27, 2018
  49. Elijah NewrenApr 27, 2018
  50. Eckhard MaaßApr 30, 2018
  51. Elijah NewrenApr 30, 2018
  52. Elijah NewrenApr 27, 2018
  53. Elijah Newren, Apr 27, 2018
  54. Ben PeartApr 30, 2018
  55. Elijah NewrenApr 30, 2018
  56. Ben PeartMay 2, 2018
  57. 3/3 merge: pass aggressive when rename detection is turned offBen Peart, Apr 26, 2018
  58. Elijah NewrenApr 26, 2018
  59. Elijah NewrenApr 26, 2018
  60. 0/3 add additional config settings for mergeBen Peart, May 2, 2018
  61. 1/3 merge: update documentation for {merge,diff}.renameLimitBen Peart, May 2, 2018
  62. 2/3 merge: Add merge.renames config settingBen Peart, May 2, 2018
  63. Junio C HamanoMay 4, 2018
  64. 3/3 merge: pass aggressive when rename detection is turned offBen Peart, May 2, 2018
  65. Elijah NewrenMay 2, 2018

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.