Merge branch 'en/merge-recursive-debug'
Remove remnants of the recursive merge strategy backend, which was
superseded by the ort merge strategy.
* en/merge-recursive-debug:
  builtin/{merge,rebase,revert}: remove GIT_TEST_MERGE_ALGORITHM
  tests: remove GIT_TEST_MERGE_ALGORITHM and test_expect_merge_algorithm
  merge-recursive.[ch]: thoroughly debug these
  merge, sequencer: switch recursive merges over to ort
  sequencer: switch non-recursive merges over to ort
  merge-ort: enable diff-algorithms other than histogram
  builtin/merge-recursive: switch to using merge_ort_generic()
  checkout: replace merge_trees() with merge_ort_nonrecursive()
			
			
				maint
			
			
		
						commit
						c3ebf18eb2
					
				|  | @ -87,6 +87,20 @@ no-renames;; | ||||||
| 	configuration variable. | 	configuration variable. | ||||||
| 	See also linkgit:git-diff[1] `--no-renames`. | 	See also linkgit:git-diff[1] `--no-renames`. | ||||||
|  |  | ||||||
|  | histogram;; | ||||||
|  | 	Deprecated synonym for `diff-algorithm=histogram`. | ||||||
|  |  | ||||||
|  | patience;; | ||||||
|  | 	Deprecated synonym for `diff-algorithm=patience`. | ||||||
|  |  | ||||||
|  | diff-algorithm=[histogram|minimal|myers|patience];; | ||||||
|  | 	Use a different diff algorithm while merging, which can help | ||||||
|  | 	avoid mismerges that occur due to unimportant matching lines | ||||||
|  | 	(such as braces from distinct functions).  See also | ||||||
|  | 	linkgit:git-diff[1] `--diff-algorithm`.  Note that `ort` | ||||||
|  | 	defaults to `diff-algorithm=histogram`, while regular diffs | ||||||
|  | 	currently default to the `diff.algorithm` config setting. | ||||||
|  |  | ||||||
| subtree[=<path>];; | subtree[=<path>];; | ||||||
| 	This option is a more advanced form of 'subtree' strategy, where | 	This option is a more advanced form of 'subtree' strategy, where | ||||||
| 	the strategy makes a guess on how two trees must be shifted to | 	the strategy makes a guess on how two trees must be shifted to | ||||||
|  | @ -95,36 +109,11 @@ subtree[=<path>];; | ||||||
| 	two trees to match. | 	two trees to match. | ||||||
|  |  | ||||||
| recursive:: | recursive:: | ||||||
| 	This can only resolve two heads using a 3-way merge | 	This is now a synonym for `ort`.  It was an alternative | ||||||
| 	algorithm.  When there is more than one common | 	implementation until v2.49.0, but was redirected to mean `ort` | ||||||
| 	ancestor that can be used for 3-way merge, it creates a | 	in v2.50.0.  The previous recursive strategy was the default | ||||||
| 	merged tree of the common ancestors and uses that as | 	strategy for resolving two heads from Git v0.99.9k until | ||||||
| 	the reference tree for the 3-way merge.  This has been | 	v2.33.0. | ||||||
| 	reported to result in fewer merge conflicts without |  | ||||||
| 	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.  It does not make use of detected copies.  This was |  | ||||||
| 	the default strategy for resolving two heads from Git v0.99.9k |  | ||||||
| 	until v2.33.0. |  | ||||||
| + |  | ||||||
| For a path that is a submodule, the same caution as 'ort' applies to this |  | ||||||
| strategy. |  | ||||||
| + |  | ||||||
| The 'recursive' strategy takes the same options as 'ort'.  However, |  | ||||||
| there are two additional options that 'ort' ignores (not documented |  | ||||||
| above) that are potentially useful with the 'recursive' strategy: |  | ||||||
|  |  | ||||||
| patience;; |  | ||||||
| 	Deprecated synonym for `diff-algorithm=patience`. |  | ||||||
|  |  | ||||||
| diff-algorithm=[patience|minimal|histogram|myers];; |  | ||||||
| 	Use a different diff algorithm while merging, which can help |  | ||||||
| 	avoid mismerges that occur due to unimportant matching lines |  | ||||||
| 	(such as braces from distinct functions).  See also |  | ||||||
| 	linkgit:git-diff[1] `--diff-algorithm`.  Note that `ort` |  | ||||||
| 	specifically uses `diff-algorithm=histogram`, while `recursive` |  | ||||||
| 	defaults to the `diff.algorithm` config setting. |  | ||||||
|  |  | ||||||
| resolve:: | resolve:: | ||||||
| 	This can only resolve two heads (i.e. the current branch | 	This can only resolve two heads (i.e. the current branch | ||||||
|  | @ -145,7 +134,7 @@ ours:: | ||||||
| 	ignoring all changes from all other branches.  It is meant to | 	ignoring all changes from all other branches.  It is meant to | ||||||
| 	be used to supersede old development history of side | 	be used to supersede old development history of side | ||||||
| 	branches.  Note that this is different from the -Xours option to | 	branches.  Note that this is different from the -Xours option to | ||||||
| 	the 'recursive' merge strategy. | 	the 'ort' merge strategy. | ||||||
|  |  | ||||||
| subtree:: | subtree:: | ||||||
| 	This is a modified `ort` strategy. When merging trees A and | 	This is a modified `ort` strategy. When merging trees A and | ||||||
|  |  | ||||||
|  | @ -356,8 +356,6 @@ understanding these differences can be beneficial. | ||||||
|     The behavior for these commands somewhat depends upon the merge |     The behavior for these commands somewhat depends upon the merge | ||||||
|     strategy being used: |     strategy being used: | ||||||
|       * `ort` behaves as described above |       * `ort` behaves as described above | ||||||
|       * `recursive` tries to not vivify files unnecessarily, but does sometimes |  | ||||||
| 	vivify files without conflicts. |  | ||||||
|       * `octopus` and `resolve` will always vivify any file changed in the merge |       * `octopus` and `resolve` will always vivify any file changed in the merge | ||||||
| 	relative to the first parent, which is rather suboptimal. | 	relative to the first parent, which is rather suboptimal. | ||||||
|  |  | ||||||
|  |  | ||||||
							
								
								
									
										1
									
								
								Makefile
								
								
								
								
							
							
						
						
									
										1
									
								
								Makefile
								
								
								
								
							|  | @ -1070,7 +1070,6 @@ LIB_OBJS += merge-blobs.o | ||||||
| LIB_OBJS += merge-ll.o | LIB_OBJS += merge-ll.o | ||||||
| LIB_OBJS += merge-ort.o | LIB_OBJS += merge-ort.o | ||||||
| LIB_OBJS += merge-ort-wrappers.o | LIB_OBJS += merge-ort-wrappers.o | ||||||
| LIB_OBJS += merge-recursive.o |  | ||||||
| LIB_OBJS += merge.o | LIB_OBJS += merge.o | ||||||
| LIB_OBJS += midx.o | LIB_OBJS += midx.o | ||||||
| LIB_OBJS += midx-write.o | LIB_OBJS += midx-write.o | ||||||
|  |  | ||||||
|  | @ -17,7 +17,7 @@ | ||||||
| #include "merge-ll.h" | #include "merge-ll.h" | ||||||
| #include "lockfile.h" | #include "lockfile.h" | ||||||
| #include "mem-pool.h" | #include "mem-pool.h" | ||||||
| #include "merge-recursive.h" | #include "merge-ort-wrappers.h" | ||||||
| #include "object-name.h" | #include "object-name.h" | ||||||
| #include "object-store-ll.h" | #include "object-store-ll.h" | ||||||
| #include "parse-options.h" | #include "parse-options.h" | ||||||
|  | @ -907,7 +907,7 @@ static int merge_working_tree(const struct checkout_opts *opts, | ||||||
| 			o.branch1 = new_branch_info->name; | 			o.branch1 = new_branch_info->name; | ||||||
| 			o.branch2 = "local"; | 			o.branch2 = "local"; | ||||||
| 			o.conflict_style = opts->conflict_style; | 			o.conflict_style = opts->conflict_style; | ||||||
| 			ret = merge_trees(&o, | 			ret = merge_ort_nonrecursive(&o, | ||||||
| 						     new_tree, | 						     new_tree, | ||||||
| 						     work, | 						     work, | ||||||
| 						     old_tree); | 						     old_tree); | ||||||
|  |  | ||||||
|  | @ -3,7 +3,7 @@ | ||||||
| #include "advice.h" | #include "advice.h" | ||||||
| #include "gettext.h" | #include "gettext.h" | ||||||
| #include "hash.h" | #include "hash.h" | ||||||
| #include "merge-recursive.h" | #include "merge-ort-wrappers.h" | ||||||
| #include "object-name.h" | #include "object-name.h" | ||||||
|  |  | ||||||
| static const char builtin_merge_recursive_usage[] = | static const char builtin_merge_recursive_usage[] = | ||||||
|  | @ -89,7 +89,7 @@ int cmd_merge_recursive(int argc, | ||||||
| 	if (o.verbosity >= 3) | 	if (o.verbosity >= 3) | ||||||
| 		printf(_("Merging %s with %s\n"), o.branch1, o.branch2); | 		printf(_("Merging %s with %s\n"), o.branch1, o.branch2); | ||||||
|  |  | ||||||
| 	failed = merge_recursive_generic(&o, &h1, &h2, bases_count, bases, &result); | 	failed = merge_ort_generic(&o, &h1, &h2, bases_count, bases, &result); | ||||||
|  |  | ||||||
| 	free(better1); | 	free(better1); | ||||||
| 	free(better2); | 	free(better2); | ||||||
|  |  | ||||||
|  | @ -39,7 +39,6 @@ | ||||||
| #include "rerere.h" | #include "rerere.h" | ||||||
| #include "help.h" | #include "help.h" | ||||||
| #include "merge.h" | #include "merge.h" | ||||||
| #include "merge-recursive.h" |  | ||||||
| #include "merge-ort-wrappers.h" | #include "merge-ort-wrappers.h" | ||||||
| #include "resolve-undo.h" | #include "resolve-undo.h" | ||||||
| #include "remote.h" | #include "remote.h" | ||||||
|  | @ -171,7 +170,7 @@ static struct strategy *get_strategy(const char *name) | ||||||
| 	struct strategy *ret; | 	struct strategy *ret; | ||||||
| 	static struct cmdnames main_cmds = {0}, other_cmds = {0}; | 	static struct cmdnames main_cmds = {0}, other_cmds = {0}; | ||||||
| 	static int loaded; | 	static int loaded; | ||||||
| 	char *default_strategy = getenv("GIT_TEST_MERGE_ALGORITHM"); | 	char *default_strategy = NULL; | ||||||
|  |  | ||||||
| 	if (!name) | 	if (!name) | ||||||
| 		return NULL; | 		return NULL; | ||||||
|  | @ -750,12 +749,8 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common, | ||||||
|  |  | ||||||
| 		repo_hold_locked_index(the_repository, &lock, | 		repo_hold_locked_index(the_repository, &lock, | ||||||
| 				       LOCK_DIE_ON_ERROR); | 				       LOCK_DIE_ON_ERROR); | ||||||
| 		if (!strcmp(strategy, "ort")) |  | ||||||
| 		clean = merge_ort_recursive(&o, head, remoteheads->item, | 		clean = merge_ort_recursive(&o, head, remoteheads->item, | ||||||
| 					    reversed, &result); | 					    reversed, &result); | ||||||
| 		else |  | ||||||
| 			clean = merge_recursive(&o, head, remoteheads->item, |  | ||||||
| 						reversed, &result); |  | ||||||
| 		free_commit_list(reversed); | 		free_commit_list(reversed); | ||||||
| 		strbuf_release(&o.obuf); | 		strbuf_release(&o.obuf); | ||||||
|  |  | ||||||
|  | @ -1316,12 +1311,6 @@ int cmd_merge(int argc, | ||||||
| 	if (branch) | 	if (branch) | ||||||
| 		skip_prefix(branch, "refs/heads/", &branch); | 		skip_prefix(branch, "refs/heads/", &branch); | ||||||
|  |  | ||||||
| 	if (!pull_twohead) { |  | ||||||
| 		char *default_strategy = getenv("GIT_TEST_MERGE_ALGORITHM"); |  | ||||||
| 		if (default_strategy && !strcmp(default_strategy, "ort")) |  | ||||||
| 			pull_twohead = xstrdup("ort"); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	init_diff_ui_defaults(); | 	init_diff_ui_defaults(); | ||||||
| 	git_config(git_merge_config, NULL); | 	git_config(git_merge_config, NULL); | ||||||
|  |  | ||||||
|  | @ -1522,12 +1511,6 @@ int cmd_merge(int argc, | ||||||
| 			fast_forward = FF_NO; | 			fast_forward = FF_NO; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (!use_strategies && !pull_twohead && |  | ||||||
| 	    remoteheads && !remoteheads->next) { |  | ||||||
| 		char *default_strategy = getenv("GIT_TEST_MERGE_ALGORITHM"); |  | ||||||
| 		if (default_strategy) |  | ||||||
| 			append_strategy(get_strategy(default_strategy)); |  | ||||||
| 	} |  | ||||||
| 	if (!use_strategies) { | 	if (!use_strategies) { | ||||||
| 		if (!remoteheads) | 		if (!remoteheads) | ||||||
| 			; /* already up-to-date */ | 			; /* already up-to-date */ | ||||||
|  |  | ||||||
|  | @ -1575,11 +1575,6 @@ int cmd_rebase(int argc, | ||||||
| 			    options.default_backend); | 			    options.default_backend); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (options.type == REBASE_MERGE && |  | ||||||
| 	    !options.strategy && |  | ||||||
| 	    getenv("GIT_TEST_MERGE_ALGORITHM")) |  | ||||||
| 		options.strategy = xstrdup(getenv("GIT_TEST_MERGE_ALGORITHM")); |  | ||||||
|  |  | ||||||
| 	switch (options.type) { | 	switch (options.type) { | ||||||
| 	case REBASE_MERGE: | 	case REBASE_MERGE: | ||||||
| 		options.state_dir = merge_dir(); | 		options.state_dir = merge_dir(); | ||||||
|  |  | ||||||
|  | @ -252,8 +252,6 @@ static int run_sequencer(int argc, const char **argv, const char *prefix, | ||||||
| 		free(opts->strategy); | 		free(opts->strategy); | ||||||
| 		opts->strategy = xstrdup_or_null(strategy); | 		opts->strategy = xstrdup_or_null(strategy); | ||||||
| 	} | 	} | ||||||
| 	if (!opts->strategy && getenv("GIT_TEST_MERGE_ALGORITHM")) |  | ||||||
| 		opts->strategy = xstrdup(getenv("GIT_TEST_MERGE_ALGORITHM")); |  | ||||||
| 	free(options); | 	free(options); | ||||||
|  |  | ||||||
| 	if (cmd == 'q') { | 	if (cmd == 'q') { | ||||||
|  |  | ||||||
|  | @ -20,7 +20,6 @@ linux-breaking-changes) | ||||||
| linux-TEST-vars) | linux-TEST-vars) | ||||||
| 	export OPENSSL_SHA1_UNSAFE=YesPlease | 	export OPENSSL_SHA1_UNSAFE=YesPlease | ||||||
| 	export GIT_TEST_SPLIT_INDEX=yes | 	export GIT_TEST_SPLIT_INDEX=yes | ||||||
| 	export GIT_TEST_MERGE_ALGORITHM=recursive |  | ||||||
| 	export GIT_TEST_FULL_IN_PACK_ARRAY=true | 	export GIT_TEST_FULL_IN_PACK_ARRAY=true | ||||||
| 	export GIT_TEST_OE_SIZE=10 | 	export GIT_TEST_OE_SIZE=10 | ||||||
| 	export GIT_TEST_OE_DELTA_SIZE=5 | 	export GIT_TEST_OE_DELTA_SIZE=5 | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| #ifndef MERGE_ORT_WRAPPERS_H | #ifndef MERGE_ORT_WRAPPERS_H | ||||||
| #define MERGE_ORT_WRAPPERS_H | #define MERGE_ORT_WRAPPERS_H | ||||||
|  |  | ||||||
| #include "merge-recursive.h" | #include "merge-ort.h" | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * rename-detecting three-way merge, no recursion. |  * rename-detecting three-way merge, no recursion. | ||||||
|  |  | ||||||
							
								
								
									
										162
									
								
								merge-ort.c
								
								
								
								
							
							
						
						
									
										162
									
								
								merge-ort.c
								
								
								
								
							|  | @ -26,6 +26,7 @@ | ||||||
| #include "cache-tree.h" | #include "cache-tree.h" | ||||||
| #include "commit.h" | #include "commit.h" | ||||||
| #include "commit-reach.h" | #include "commit-reach.h" | ||||||
|  | #include "config.h" | ||||||
| #include "diff.h" | #include "diff.h" | ||||||
| #include "diffcore.h" | #include "diffcore.h" | ||||||
| #include "dir.h" | #include "dir.h" | ||||||
|  | @ -4957,9 +4958,6 @@ static void merge_start(struct merge_options *opt, struct merge_result *result) | ||||||
| 	} | 	} | ||||||
| 	trace2_region_leave("merge", "sanity checks", opt->repo); | 	trace2_region_leave("merge", "sanity checks", opt->repo); | ||||||
|  |  | ||||||
| 	/* Default to histogram diff.  Actually, just hardcode it...for now. */ |  | ||||||
| 	opt->xdl_opts = DIFF_WITH_ALG(opt, HISTOGRAM_DIFF); |  | ||||||
|  |  | ||||||
| 	/* Handle attr direction stuff for renormalization */ | 	/* Handle attr direction stuff for renormalization */ | ||||||
| 	if (opt->renormalize) | 	if (opt->renormalize) | ||||||
| 		git_attr_set_direction(GIT_ATTR_CHECKOUT); | 		git_attr_set_direction(GIT_ATTR_CHECKOUT); | ||||||
|  | @ -5325,3 +5323,161 @@ void merge_incore_recursive(struct merge_options *opt, | ||||||
| 	merge_ort_internal(opt, merge_bases, side1, side2, result); | 	merge_ort_internal(opt, merge_bases, side1, side2, result); | ||||||
| 	trace2_region_leave("merge", "incore_recursive", opt->repo); | 	trace2_region_leave("merge", "incore_recursive", opt->repo); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static void merge_recursive_config(struct merge_options *opt, int ui) | ||||||
|  | { | ||||||
|  | 	char *value = NULL; | ||||||
|  | 	int renormalize = 0; | ||||||
|  | 	git_config_get_int("merge.verbosity", &opt->verbosity); | ||||||
|  | 	git_config_get_int("diff.renamelimit", &opt->rename_limit); | ||||||
|  | 	git_config_get_int("merge.renamelimit", &opt->rename_limit); | ||||||
|  | 	git_config_get_bool("merge.renormalize", &renormalize); | ||||||
|  | 	opt->renormalize = renormalize; | ||||||
|  | 	if (!git_config_get_string("diff.renames", &value)) { | ||||||
|  | 		opt->detect_renames = git_config_rename("diff.renames", value); | ||||||
|  | 		free(value); | ||||||
|  | 	} | ||||||
|  | 	if (!git_config_get_string("merge.renames", &value)) { | ||||||
|  | 		opt->detect_renames = git_config_rename("merge.renames", value); | ||||||
|  | 		free(value); | ||||||
|  | 	} | ||||||
|  | 	if (!git_config_get_string("merge.directoryrenames", &value)) { | ||||||
|  | 		int boolval = git_parse_maybe_bool(value); | ||||||
|  | 		if (0 <= boolval) { | ||||||
|  | 			opt->detect_directory_renames = boolval ? | ||||||
|  | 				MERGE_DIRECTORY_RENAMES_TRUE : | ||||||
|  | 				MERGE_DIRECTORY_RENAMES_NONE; | ||||||
|  | 		} else if (!strcasecmp(value, "conflict")) { | ||||||
|  | 			opt->detect_directory_renames = | ||||||
|  | 				MERGE_DIRECTORY_RENAMES_CONFLICT; | ||||||
|  | 		} /* avoid erroring on values from future versions of git */ | ||||||
|  | 		free(value); | ||||||
|  | 	} | ||||||
|  | 	if (ui) { | ||||||
|  | 		if (!git_config_get_string("diff.algorithm", &value)) { | ||||||
|  | 			long diff_algorithm = parse_algorithm_value(value); | ||||||
|  | 			if (diff_algorithm < 0) | ||||||
|  | 				die(_("unknown value for config '%s': %s"), "diff.algorithm", value); | ||||||
|  | 			opt->xdl_opts = (opt->xdl_opts & ~XDF_DIFF_ALGORITHM_MASK) | diff_algorithm; | ||||||
|  | 			free(value); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	git_config(git_xmerge_config, NULL); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void init_merge_options(struct merge_options *opt, | ||||||
|  | 			struct repository *repo, int ui) | ||||||
|  | { | ||||||
|  | 	const char *merge_verbosity; | ||||||
|  | 	memset(opt, 0, sizeof(struct merge_options)); | ||||||
|  |  | ||||||
|  | 	opt->repo = repo; | ||||||
|  |  | ||||||
|  | 	opt->detect_renames = -1; | ||||||
|  | 	opt->detect_directory_renames = MERGE_DIRECTORY_RENAMES_CONFLICT; | ||||||
|  | 	opt->rename_limit = -1; | ||||||
|  |  | ||||||
|  | 	opt->verbosity = 2; | ||||||
|  | 	opt->buffer_output = 1; | ||||||
|  | 	strbuf_init(&opt->obuf, 0); | ||||||
|  |  | ||||||
|  | 	opt->renormalize = 0; | ||||||
|  |  | ||||||
|  | 	opt->conflict_style = -1; | ||||||
|  | 	opt->xdl_opts = DIFF_WITH_ALG(opt, HISTOGRAM_DIFF); | ||||||
|  |  | ||||||
|  | 	merge_recursive_config(opt, ui); | ||||||
|  | 	merge_verbosity = getenv("GIT_MERGE_VERBOSITY"); | ||||||
|  | 	if (merge_verbosity) | ||||||
|  | 		opt->verbosity = strtol(merge_verbosity, NULL, 10); | ||||||
|  | 	if (opt->verbosity >= 5) | ||||||
|  | 		opt->buffer_output = 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void init_ui_merge_options(struct merge_options *opt, | ||||||
|  | 			struct repository *repo) | ||||||
|  | { | ||||||
|  | 	init_merge_options(opt, repo, 1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void init_basic_merge_options(struct merge_options *opt, | ||||||
|  | 			struct repository *repo) | ||||||
|  | { | ||||||
|  | 	init_merge_options(opt, repo, 0); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * For now, members of merge_options do not need deep copying, but | ||||||
|  |  * it may change in the future, in which case we would need to update | ||||||
|  |  * this, and also make a matching change to clear_merge_options() to | ||||||
|  |  * release the resources held by a copied instance. | ||||||
|  |  */ | ||||||
|  | void copy_merge_options(struct merge_options *dst, struct merge_options *src) | ||||||
|  | { | ||||||
|  | 	*dst = *src; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void clear_merge_options(struct merge_options *opt UNUSED) | ||||||
|  | { | ||||||
|  | 	; /* no-op as our copy is shallow right now */ | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int parse_merge_opt(struct merge_options *opt, const char *s) | ||||||
|  | { | ||||||
|  | 	const char *arg; | ||||||
|  |  | ||||||
|  | 	if (!s || !*s) | ||||||
|  | 		return -1; | ||||||
|  | 	if (!strcmp(s, "ours")) | ||||||
|  | 		opt->recursive_variant = MERGE_VARIANT_OURS; | ||||||
|  | 	else if (!strcmp(s, "theirs")) | ||||||
|  | 		opt->recursive_variant = MERGE_VARIANT_THEIRS; | ||||||
|  | 	else if (!strcmp(s, "subtree")) | ||||||
|  | 		opt->subtree_shift = ""; | ||||||
|  | 	else if (skip_prefix(s, "subtree=", &arg)) | ||||||
|  | 		opt->subtree_shift = arg; | ||||||
|  | 	else if (!strcmp(s, "patience")) | ||||||
|  | 		opt->xdl_opts = DIFF_WITH_ALG(opt, PATIENCE_DIFF); | ||||||
|  | 	else if (!strcmp(s, "histogram")) | ||||||
|  | 		opt->xdl_opts = DIFF_WITH_ALG(opt, HISTOGRAM_DIFF); | ||||||
|  | 	else if (skip_prefix(s, "diff-algorithm=", &arg)) { | ||||||
|  | 		long value = parse_algorithm_value(arg); | ||||||
|  | 		if (value < 0) | ||||||
|  | 			return -1; | ||||||
|  | 		/* clear out previous settings */ | ||||||
|  | 		DIFF_XDL_CLR(opt, NEED_MINIMAL); | ||||||
|  | 		opt->xdl_opts &= ~XDF_DIFF_ALGORITHM_MASK; | ||||||
|  | 		opt->xdl_opts |= value; | ||||||
|  | 	} | ||||||
|  | 	else if (!strcmp(s, "ignore-space-change")) | ||||||
|  | 		DIFF_XDL_SET(opt, IGNORE_WHITESPACE_CHANGE); | ||||||
|  | 	else if (!strcmp(s, "ignore-all-space")) | ||||||
|  | 		DIFF_XDL_SET(opt, IGNORE_WHITESPACE); | ||||||
|  | 	else if (!strcmp(s, "ignore-space-at-eol")) | ||||||
|  | 		DIFF_XDL_SET(opt, IGNORE_WHITESPACE_AT_EOL); | ||||||
|  | 	else if (!strcmp(s, "ignore-cr-at-eol")) | ||||||
|  | 		DIFF_XDL_SET(opt, IGNORE_CR_AT_EOL); | ||||||
|  | 	else if (!strcmp(s, "renormalize")) | ||||||
|  | 		opt->renormalize = 1; | ||||||
|  | 	else if (!strcmp(s, "no-renormalize")) | ||||||
|  | 		opt->renormalize = 0; | ||||||
|  | 	else if (!strcmp(s, "no-renames")) | ||||||
|  | 		opt->detect_renames = 0; | ||||||
|  | 	else if (!strcmp(s, "find-renames")) { | ||||||
|  | 		opt->detect_renames = 1; | ||||||
|  | 		opt->rename_score = 0; | ||||||
|  | 	} | ||||||
|  | 	else if (skip_prefix(s, "find-renames=", &arg) || | ||||||
|  | 		 skip_prefix(s, "rename-threshold=", &arg)) { | ||||||
|  | 		if ((opt->rename_score = parse_rename_score(&arg)) == -1 || *arg != 0) | ||||||
|  | 			return -1; | ||||||
|  | 		opt->detect_renames = 1; | ||||||
|  | 	} | ||||||
|  | 	/* | ||||||
|  | 	 * Please update $__git_merge_strategy_options in | ||||||
|  | 	 * git-completion.bash when you add new options | ||||||
|  | 	 */ | ||||||
|  | 	else | ||||||
|  | 		return -1; | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
							
								
								
									
										60
									
								
								merge-ort.h
								
								
								
								
							
							
						
						
									
										60
									
								
								merge-ort.h
								
								
								
								
							|  | @ -1,10 +1,11 @@ | ||||||
| #ifndef MERGE_ORT_H | #ifndef MERGE_ORT_H | ||||||
| #define MERGE_ORT_H | #define MERGE_ORT_H | ||||||
|  |  | ||||||
| #include "merge-recursive.h" |  | ||||||
| #include "hash.h" | #include "hash.h" | ||||||
|  | #include "strbuf.h" | ||||||
|  |  | ||||||
| struct commit; | struct commit; | ||||||
|  | struct commit_list; | ||||||
| struct tree; | struct tree; | ||||||
| struct strmap; | struct strmap; | ||||||
|  |  | ||||||
|  | @ -44,6 +45,51 @@ struct merge_result { | ||||||
| 	unsigned _properly_initialized; | 	unsigned _properly_initialized; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | struct merge_options_internal; | ||||||
|  | struct merge_options { | ||||||
|  | 	struct repository *repo; | ||||||
|  |  | ||||||
|  | 	/* ref names used in console messages and conflict markers */ | ||||||
|  | 	const char *ancestor; | ||||||
|  | 	const char *branch1; | ||||||
|  | 	const char *branch2; | ||||||
|  |  | ||||||
|  | 	/* rename related options */ | ||||||
|  | 	int detect_renames; | ||||||
|  | 	enum { | ||||||
|  | 		MERGE_DIRECTORY_RENAMES_NONE = 0, | ||||||
|  | 		MERGE_DIRECTORY_RENAMES_CONFLICT = 1, | ||||||
|  | 		MERGE_DIRECTORY_RENAMES_TRUE = 2 | ||||||
|  | 	} detect_directory_renames; | ||||||
|  | 	int rename_limit; | ||||||
|  | 	int rename_score; | ||||||
|  | 	int show_rename_progress; | ||||||
|  |  | ||||||
|  | 	/* xdiff-related options (patience, ignore whitespace, ours/theirs) */ | ||||||
|  | 	long xdl_opts; | ||||||
|  | 	int conflict_style; | ||||||
|  | 	enum { | ||||||
|  | 		MERGE_VARIANT_NORMAL = 0, | ||||||
|  | 		MERGE_VARIANT_OURS, | ||||||
|  | 		MERGE_VARIANT_THEIRS | ||||||
|  | 	} recursive_variant; | ||||||
|  |  | ||||||
|  | 	/* console output related options */ | ||||||
|  | 	int verbosity; | ||||||
|  | 	unsigned buffer_output; /* 1: output at end, 2: keep buffered */ | ||||||
|  | 	struct strbuf obuf;     /* output buffer; if buffer_output == 2, caller | ||||||
|  | 				 * must handle and call strbuf_release */ | ||||||
|  |  | ||||||
|  | 	/* miscellaneous control options */ | ||||||
|  | 	const char *subtree_shift; | ||||||
|  | 	unsigned renormalize : 1; | ||||||
|  | 	unsigned record_conflict_msgs_as_headers : 1; | ||||||
|  | 	const char *msg_header_prefix; | ||||||
|  |  | ||||||
|  | 	/* internal fields used by the implementation */ | ||||||
|  | 	struct merge_options_internal *priv; | ||||||
|  | }; | ||||||
|  |  | ||||||
| /* Mostly internal function also used by merge-ort-wrappers.c */ | /* Mostly internal function also used by merge-ort-wrappers.c */ | ||||||
| struct commit *make_virtual_commit(struct repository *repo, | struct commit *make_virtual_commit(struct repository *repo, | ||||||
| 				   struct tree *tree, | 				   struct tree *tree, | ||||||
|  | @ -119,4 +165,16 @@ void merge_get_conflicted_files(struct merge_result *result, | ||||||
| void merge_finalize(struct merge_options *opt, | void merge_finalize(struct merge_options *opt, | ||||||
| 		    struct merge_result *result); | 		    struct merge_result *result); | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* for use by porcelain commands */ | ||||||
|  | void init_ui_merge_options(struct merge_options *opt, struct repository *repo); | ||||||
|  | /* for use by plumbing commands */ | ||||||
|  | void init_basic_merge_options(struct merge_options *opt, struct repository *repo); | ||||||
|  |  | ||||||
|  | void copy_merge_options(struct merge_options *dst, struct merge_options *src); | ||||||
|  | void clear_merge_options(struct merge_options *opt); | ||||||
|  |  | ||||||
|  | /* parse the option in s and update the relevant field of opt */ | ||||||
|  | int parse_merge_opt(struct merge_options *opt, const char *s); | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
							
								
								
									
										4079
									
								
								merge-recursive.c
								
								
								
								
							
							
						
						
									
										4079
									
								
								merge-recursive.c
								
								
								
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -1,132 +0,0 @@ | ||||||
| #ifndef MERGE_RECURSIVE_H |  | ||||||
| #define MERGE_RECURSIVE_H |  | ||||||
|  |  | ||||||
| #include "strbuf.h" |  | ||||||
|  |  | ||||||
| struct commit; |  | ||||||
| struct commit_list; |  | ||||||
| struct object_id; |  | ||||||
| struct repository; |  | ||||||
| struct tree; |  | ||||||
|  |  | ||||||
| struct merge_options_internal; |  | ||||||
| struct merge_options { |  | ||||||
| 	struct repository *repo; |  | ||||||
|  |  | ||||||
| 	/* ref names used in console messages and conflict markers */ |  | ||||||
| 	const char *ancestor; |  | ||||||
| 	const char *branch1; |  | ||||||
| 	const char *branch2; |  | ||||||
|  |  | ||||||
| 	/* rename related options */ |  | ||||||
| 	int detect_renames; |  | ||||||
| 	enum { |  | ||||||
| 		MERGE_DIRECTORY_RENAMES_NONE = 0, |  | ||||||
| 		MERGE_DIRECTORY_RENAMES_CONFLICT = 1, |  | ||||||
| 		MERGE_DIRECTORY_RENAMES_TRUE = 2 |  | ||||||
| 	} detect_directory_renames; |  | ||||||
| 	int rename_limit; |  | ||||||
| 	int rename_score; |  | ||||||
| 	int show_rename_progress; |  | ||||||
|  |  | ||||||
| 	/* xdiff-related options (patience, ignore whitespace, ours/theirs) */ |  | ||||||
| 	long xdl_opts; |  | ||||||
| 	int conflict_style; |  | ||||||
| 	enum { |  | ||||||
| 		MERGE_VARIANT_NORMAL = 0, |  | ||||||
| 		MERGE_VARIANT_OURS, |  | ||||||
| 		MERGE_VARIANT_THEIRS |  | ||||||
| 	} recursive_variant; |  | ||||||
|  |  | ||||||
| 	/* console output related options */ |  | ||||||
| 	int verbosity; |  | ||||||
| 	unsigned buffer_output; /* 1: output at end, 2: keep buffered */ |  | ||||||
| 	struct strbuf obuf;     /* output buffer; if buffer_output == 2, caller |  | ||||||
| 				 * must handle and call strbuf_release */ |  | ||||||
|  |  | ||||||
| 	/* miscellaneous control options */ |  | ||||||
| 	const char *subtree_shift; |  | ||||||
| 	unsigned renormalize : 1; |  | ||||||
| 	unsigned record_conflict_msgs_as_headers : 1; |  | ||||||
| 	const char *msg_header_prefix; |  | ||||||
|  |  | ||||||
| 	/* internal fields used by the implementation */ |  | ||||||
| 	struct merge_options_internal *priv; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /* for use by porcelain commands */ |  | ||||||
| void init_ui_merge_options(struct merge_options *opt, struct repository *repo); |  | ||||||
| /* for use by plumbing commands */ |  | ||||||
| void init_basic_merge_options(struct merge_options *opt, struct repository *repo); |  | ||||||
|  |  | ||||||
| void copy_merge_options(struct merge_options *dst, struct merge_options *src); |  | ||||||
| void clear_merge_options(struct merge_options *opt); |  | ||||||
|  |  | ||||||
| /* parse the option in s and update the relevant field of opt */ |  | ||||||
| int parse_merge_opt(struct merge_options *opt, const char *s); |  | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * RETURN VALUES: All the merge_* functions below return a value as follows: |  | ||||||
|  *   > 0     Merge was clean |  | ||||||
|  *   = 0     Merge had conflicts |  | ||||||
|  *   < 0     Merge hit an unexpected and unrecoverable problem (e.g. disk |  | ||||||
|  *             full) and aborted merge part-way through. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * rename-detecting three-way merge, no recursion. |  | ||||||
|  * |  | ||||||
|  * Outputs: |  | ||||||
|  *   - See RETURN VALUES above |  | ||||||
|  *   - opt->repo->index has the new index |  | ||||||
|  *   - new index NOT written to disk |  | ||||||
|  *   - The working tree is updated with results of the merge |  | ||||||
|  */ |  | ||||||
| int merge_trees(struct merge_options *opt, |  | ||||||
| 		struct tree *head, |  | ||||||
| 		struct tree *merge, |  | ||||||
| 		struct tree *merge_base); |  | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * merge_recursive is like merge_trees() but with recursive ancestor |  | ||||||
|  * consolidation. |  | ||||||
|  * |  | ||||||
|  * NOTE: empirically, about a decade ago it was determined that with more |  | ||||||
|  *       than two merge bases, optimal behavior was found when the |  | ||||||
|  *       merge_bases were passed in the order of oldest commit to newest |  | ||||||
|  *       commit.  Also, merge_bases will be consumed (emptied) so make a |  | ||||||
|  *       copy if you need it. |  | ||||||
|  * |  | ||||||
|  * Outputs: |  | ||||||
|  *   - See RETURN VALUES above |  | ||||||
|  *   - *result is treated as scratch space for temporary recursive merges |  | ||||||
|  *   - opt->repo->index has the new index |  | ||||||
|  *   - new index NOT written to disk |  | ||||||
|  *   - The working tree is updated with results of the merge |  | ||||||
|  */ |  | ||||||
| int merge_recursive(struct merge_options *opt, |  | ||||||
| 		    struct commit *h1, |  | ||||||
| 		    struct commit *h2, |  | ||||||
| 		    const struct commit_list *merge_bases, |  | ||||||
| 		    struct commit **result); |  | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * merge_recursive_generic can operate on trees instead of commits, by |  | ||||||
|  * wrapping the trees into virtual commits, and calling merge_recursive(). |  | ||||||
|  * It also writes out the in-memory index to disk if the merge is successful. |  | ||||||
|  * |  | ||||||
|  * Outputs: |  | ||||||
|  *   - See RETURN VALUES above |  | ||||||
|  *   - *result is treated as scratch space for temporary recursive merges |  | ||||||
|  *   - opt->repo->index has the new index |  | ||||||
|  *   - new index also written to $GIT_INDEX_FILE on disk |  | ||||||
|  *   - The working tree is updated with results of the merge |  | ||||||
|  */ |  | ||||||
| int merge_recursive_generic(struct merge_options *opt, |  | ||||||
| 			    const struct object_id *head, |  | ||||||
| 			    const struct object_id *merge, |  | ||||||
| 			    int num_merge_bases, |  | ||||||
| 			    const struct object_id *merge_bases, |  | ||||||
| 			    struct commit **result); |  | ||||||
|  |  | ||||||
| #endif |  | ||||||
|  | @ -372,7 +372,6 @@ libgit_sources = [ | ||||||
|   'merge-ll.c', |   'merge-ll.c', | ||||||
|   'merge-ort.c', |   'merge-ort.c', | ||||||
|   'merge-ort-wrappers.c', |   'merge-ort-wrappers.c', | ||||||
|   'merge-recursive.c', |  | ||||||
|   'merge.c', |   'merge.c', | ||||||
|   'midx.c', |   'midx.c', | ||||||
|   'midx-write.c', |   'midx-write.c', | ||||||
|  |  | ||||||
							
								
								
									
										22
									
								
								sequencer.c
								
								
								
								
							
							
						
						
									
										22
									
								
								sequencer.c
								
								
								
								
							|  | @ -781,10 +781,8 @@ static int do_recursive_merge(struct repository *r, | ||||||
| 	for (i = 0; i < opts->xopts.nr; i++) | 	for (i = 0; i < opts->xopts.nr; i++) | ||||||
| 		parse_merge_opt(&o, opts->xopts.v[i]); | 		parse_merge_opt(&o, opts->xopts.v[i]); | ||||||
|  |  | ||||||
| 	if (!opts->strategy || !strcmp(opts->strategy, "ort")) { |  | ||||||
| 	memset(&result, 0, sizeof(result)); | 	memset(&result, 0, sizeof(result)); | ||||||
| 		merge_incore_nonrecursive(&o, base_tree, head_tree, next_tree, | 	merge_incore_nonrecursive(&o, base_tree, head_tree, next_tree, &result); | ||||||
| 					    &result); |  | ||||||
| 	show_output = !is_rebase_i(opts) || !result.clean; | 	show_output = !is_rebase_i(opts) || !result.clean; | ||||||
| 	/* | 	/* | ||||||
| 	 * TODO: merge_switch_to_result will update index/working tree; | 	 * TODO: merge_switch_to_result will update index/working tree; | ||||||
|  | @ -796,13 +794,6 @@ static int do_recursive_merge(struct repository *r, | ||||||
| 	 */ | 	 */ | ||||||
| 	merge_switch_to_result(&o, head_tree, &result, 1, show_output); | 	merge_switch_to_result(&o, head_tree, &result, 1, show_output); | ||||||
| 	clean = result.clean; | 	clean = result.clean; | ||||||
| 	} else { |  | ||||||
| 		ensure_full_index(r->index); |  | ||||||
| 		clean = merge_trees(&o, head_tree, next_tree, base_tree); |  | ||||||
| 		if (is_rebase_i(opts) && clean <= 0) |  | ||||||
| 			fputs(o.obuf.buf, stdout); |  | ||||||
| 		strbuf_release(&o.obuf); |  | ||||||
| 	} |  | ||||||
| 	if (clean < 0) { | 	if (clean < 0) { | ||||||
| 		rollback_lock_file(&index_lock); | 		rollback_lock_file(&index_lock); | ||||||
| 		return clean; | 		return clean; | ||||||
|  | @ -4328,20 +4319,13 @@ static int do_merge(struct repository *r, | ||||||
| 	o.branch2 = ref_name.buf; | 	o.branch2 = ref_name.buf; | ||||||
| 	o.buffer_output = 2; | 	o.buffer_output = 2; | ||||||
|  |  | ||||||
| 	if (!opts->strategy || !strcmp(opts->strategy, "ort")) { |  | ||||||
| 	/* | 	/* | ||||||
| 	 * TODO: Should use merge_incore_recursive() and | 	 * TODO: Should use merge_incore_recursive() and | ||||||
| 	 * merge_switch_to_result(), skipping the call to | 	 * merge_switch_to_result(), skipping the call to | ||||||
| 	 * merge_switch_to_result() when we don't actually need to | 	 * merge_switch_to_result() when we don't actually need to | ||||||
| 	 * update the index and working copy immediately. | 	 * update the index and working copy immediately. | ||||||
| 	 */ | 	 */ | ||||||
| 		ret = merge_ort_recursive(&o, | 	ret = merge_ort_recursive(&o, head_commit, merge_commit, bases, &i); | ||||||
| 					  head_commit, merge_commit, bases, |  | ||||||
| 					  &i); |  | ||||||
| 	} else { |  | ||||||
| 		ret = merge_recursive(&o, head_commit, merge_commit, bases, |  | ||||||
| 				      &i); |  | ||||||
| 	} |  | ||||||
| 	if (ret <= 0) | 	if (ret <= 0) | ||||||
| 		fputs(o.obuf.buf, stdout); | 		fputs(o.obuf.buf, stdout); | ||||||
| 	strbuf_release(&o.obuf); | 	strbuf_release(&o.obuf); | ||||||
|  | @ -4352,7 +4336,7 @@ static int do_merge(struct repository *r, | ||||||
| 		goto leave_merge; | 		goto leave_merge; | ||||||
| 	} | 	} | ||||||
| 	/* | 	/* | ||||||
| 	 * The return value of merge_recursive() is 1 on clean, and 0 on | 	 * The return value of merge_ort_recursive() is 1 on clean, and 0 on | ||||||
| 	 * unclean merge. | 	 * unclean merge. | ||||||
| 	 * | 	 * | ||||||
| 	 * Let's reverse that, so that do_merge() returns 0 upon success and | 	 * Let's reverse that, so that do_merge() returns 0 upon success and | ||||||
|  |  | ||||||
|  | @ -1,13 +0,0 @@ | ||||||
| # Helper functions used by merge tests. |  | ||||||
|  |  | ||||||
| test_expect_merge_algorithm () { |  | ||||||
| 	status_for_recursive=$1 status_for_ort=$2 |  | ||||||
| 	shift 2 |  | ||||||
|  |  | ||||||
| 	if test "$GIT_TEST_MERGE_ALGORITHM" = ort |  | ||||||
| 	then |  | ||||||
| 		test_expect_${status_for_ort} "$@" |  | ||||||
| 	else |  | ||||||
| 		test_expect_${status_for_recursive} "$@" |  | ||||||
| 	fi |  | ||||||
| } |  | ||||||
|  | @ -1486,7 +1486,6 @@ test_expect_success 'sparse-index is not expanded' ' | ||||||
| 	ensure_not_expanded checkout -f update-deep && | 	ensure_not_expanded checkout -f update-deep && | ||||||
| 	test_config -C sparse-index pull.twohead ort && | 	test_config -C sparse-index pull.twohead ort && | ||||||
| 	( | 	( | ||||||
| 		sane_unset GIT_TEST_MERGE_ALGORITHM && |  | ||||||
| 		for OPERATION in "merge -m merge" cherry-pick rebase | 		for OPERATION in "merge -m merge" cherry-pick rebase | ||||||
| 		do | 		do | ||||||
| 			ensure_not_expanded merge -m merge update-folder1 && | 			ensure_not_expanded merge -m merge update-folder1 && | ||||||
|  | @ -1506,7 +1505,6 @@ test_expect_success 'sparse-index is not expanded: merge conflict in cone' ' | ||||||
| 	done && | 	done && | ||||||
|  |  | ||||||
| 	( | 	( | ||||||
| 		sane_unset GIT_TEST_MERGE_ALGORITHM && |  | ||||||
| 		git -C sparse-index config pull.twohead ort && | 		git -C sparse-index config pull.twohead ort && | ||||||
| 		ensure_not_expanded ! merge -m merged expand-right | 		ensure_not_expanded ! merge -m merged expand-right | ||||||
| 	) | 	) | ||||||
|  |  | ||||||
|  | @ -117,8 +117,6 @@ test_expect_success 'merge fails if cwd needs to be removed; recursive friendly' | ||||||
| 	grep "Refusing to remove the current working directory" error | 	grep "Refusing to remove the current working directory" error | ||||||
| ' | ' | ||||||
|  |  | ||||||
| GIT_TEST_MERGE_ALGORITHM=ort |  | ||||||
|  |  | ||||||
| test_expect_success 'merge fails if cwd needs to be removed' ' | test_expect_success 'merge fails if cwd needs to be removed' ' | ||||||
| 	test_required_dir_removal git merge fd_conflict | 	test_required_dir_removal git merge fd_conflict | ||||||
| ' | ' | ||||||
|  |  | ||||||
|  | @ -8,11 +8,6 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME | ||||||
| . ./test-lib.sh | . ./test-lib.sh | ||||||
| . "$TEST_DIRECTORY"/lib-submodule-update.sh | . "$TEST_DIRECTORY"/lib-submodule-update.sh | ||||||
|  |  | ||||||
| if test "$GIT_TEST_MERGE_ALGORITHM" != ort |  | ||||||
| then |  | ||||||
| 	KNOWN_FAILURE_NOFF_MERGE_DOESNT_CREATE_EMPTY_SUBMODULE_DIR=1 |  | ||||||
| 	KNOWN_FAILURE_NOFF_MERGE_ATTEMPTS_TO_MERGE_REMOVED_SUBMODULE_FILES=1 |  | ||||||
| fi |  | ||||||
| test_submodule_switch "cherry-pick" | test_submodule_switch "cherry-pick" | ||||||
|  |  | ||||||
| test_expect_success 'unrelated submodule/file conflict is ignored' ' | test_expect_success 'unrelated submodule/file conflict is ignored' ' | ||||||
|  |  | ||||||
|  | @ -30,10 +30,6 @@ git_revert () { | ||||||
| 	git revert HEAD | 	git revert HEAD | ||||||
| } | } | ||||||
|  |  | ||||||
| if test "$GIT_TEST_MERGE_ALGORITHM" != ort |  | ||||||
| then |  | ||||||
| 	KNOWN_FAILURE_NOFF_MERGE_DOESNT_CREATE_EMPTY_SUBMODULE_DIR=1 |  | ||||||
| fi |  | ||||||
| test_submodule_switch_func "git_revert" | test_submodule_switch_func "git_revert" | ||||||
|  |  | ||||||
| test_done | test_done | ||||||
|  |  | ||||||
|  | @ -4,13 +4,6 @@ test_description='remerge-diff handling' | ||||||
|  |  | ||||||
| . ./test-lib.sh | . ./test-lib.sh | ||||||
|  |  | ||||||
| # This test is ort-specific |  | ||||||
| if test "${GIT_TEST_MERGE_ALGORITHM}" != ort |  | ||||||
| then |  | ||||||
| 	skip_all="GIT_TEST_MERGE_ALGORITHM != ort" |  | ||||||
| 	test_done |  | ||||||
| fi |  | ||||||
|  |  | ||||||
| test_expect_success 'setup basic merges' ' | test_expect_success 'setup basic merges' ' | ||||||
| 	test_write_lines 1 2 3 4 5 6 7 8 9 >numbers && | 	test_write_lines 1 2 3 4 5 6 7 8 9 >numbers && | ||||||
| 	git add numbers && | 	git add numbers && | ||||||
|  |  | ||||||
|  | @ -4,13 +4,6 @@ test_description='git merge-tree --write-tree' | ||||||
|  |  | ||||||
| . ./test-lib.sh | . ./test-lib.sh | ||||||
|  |  | ||||||
| # This test is ort-specific |  | ||||||
| if test "$GIT_TEST_MERGE_ALGORITHM" != "ort" |  | ||||||
| then |  | ||||||
| 	skip_all="GIT_TEST_MERGE_ALGORITHM != ort" |  | ||||||
| 	test_done |  | ||||||
| fi |  | ||||||
|  |  | ||||||
| test_expect_success setup ' | test_expect_success setup ' | ||||||
| 	test_write_lines 1 2 3 4 5 >numbers && | 	test_write_lines 1 2 3 4 5 >numbers && | ||||||
| 	echo hello >greeting && | 	echo hello >greeting && | ||||||
|  |  | ||||||
|  | @ -45,11 +45,6 @@ git_pull_noff () { | ||||||
| 	$2 git pull --no-ff | 	$2 git pull --no-ff | ||||||
| } | } | ||||||
|  |  | ||||||
| if test "$GIT_TEST_MERGE_ALGORITHM" != ort |  | ||||||
| then |  | ||||||
| 	KNOWN_FAILURE_NOFF_MERGE_DOESNT_CREATE_EMPTY_SUBMODULE_DIR=1 |  | ||||||
| 	KNOWN_FAILURE_NOFF_MERGE_ATTEMPTS_TO_MERGE_REMOVED_SUBMODULE_FILES=1 |  | ||||||
| fi |  | ||||||
| test_submodule_switch_func "git_pull_noff" | test_submodule_switch_func "git_pull_noff" | ||||||
|  |  | ||||||
| test_expect_success 'setup' ' | test_expect_success 'setup' ' | ||||||
|  |  | ||||||
|  | @ -84,12 +84,7 @@ test_expect_success 'modify/delete + directory/file conflict' ' | ||||||
|  |  | ||||||
| 	test_stdout_line_count = 5 git ls-files -s && | 	test_stdout_line_count = 5 git ls-files -s && | ||||||
| 	test_stdout_line_count = 4 git ls-files -u && | 	test_stdout_line_count = 4 git ls-files -u && | ||||||
| 	if test "$GIT_TEST_MERGE_ALGORITHM" = ort | 	test_stdout_line_count = 0 git ls-files -o && | ||||||
| 	then |  | ||||||
| 		test_stdout_line_count = 0 git ls-files -o |  | ||||||
| 	else |  | ||||||
| 		test_stdout_line_count = 1 git ls-files -o |  | ||||||
| 	fi && |  | ||||||
|  |  | ||||||
| 	test_path_is_file letters/file && | 	test_path_is_file letters/file && | ||||||
| 	test_path_is_file letters.txt && | 	test_path_is_file letters.txt && | ||||||
|  | @ -105,12 +100,7 @@ test_expect_success 'modify/delete + directory/file conflict; other way' ' | ||||||
|  |  | ||||||
| 	test_stdout_line_count = 5 git ls-files -s && | 	test_stdout_line_count = 5 git ls-files -s && | ||||||
| 	test_stdout_line_count = 4 git ls-files -u && | 	test_stdout_line_count = 4 git ls-files -u && | ||||||
| 	if test "$GIT_TEST_MERGE_ALGORITHM" = ort | 	test_stdout_line_count = 0 git ls-files -o && | ||||||
| 	then |  | ||||||
| 		test_stdout_line_count = 0 git ls-files -o |  | ||||||
| 	else |  | ||||||
| 		test_stdout_line_count = 1 git ls-files -o |  | ||||||
| 	fi && |  | ||||||
|  |  | ||||||
| 	test_path_is_file letters/file && | 	test_path_is_file letters/file && | ||||||
| 	test_path_is_file letters.txt && | 	test_path_is_file letters.txt && | ||||||
|  |  | ||||||
|  | @ -313,12 +313,7 @@ test_expect_success 'Rename+D/F conflict; renamed file merges but dir in way' ' | ||||||
|  |  | ||||||
| 	test_grep "CONFLICT (modify/delete): dir/file-in-the-way" output && | 	test_grep "CONFLICT (modify/delete): dir/file-in-the-way" output && | ||||||
| 	test_grep "Auto-merging dir" output && | 	test_grep "Auto-merging dir" output && | ||||||
| 	if test "$GIT_TEST_MERGE_ALGORITHM" = ort | 	test_grep "moving it to dir~HEAD instead" output && | ||||||
| 	then |  | ||||||
| 		test_grep "moving it to dir~HEAD instead" output |  | ||||||
| 	else |  | ||||||
| 		test_grep "Adding as dir~HEAD instead" output |  | ||||||
| 	fi && |  | ||||||
|  |  | ||||||
| 	test_stdout_line_count = 3 git ls-files -u && | 	test_stdout_line_count = 3 git ls-files -u && | ||||||
| 	test_stdout_line_count = 2 git ls-files -u dir/file-in-the-way && | 	test_stdout_line_count = 2 git ls-files -u dir/file-in-the-way && | ||||||
|  | @ -340,12 +335,7 @@ test_expect_success 'Same as previous, but merged other way' ' | ||||||
| 	! grep "error: refusing to lose untracked file at" errors && | 	! grep "error: refusing to lose untracked file at" errors && | ||||||
| 	test_grep "CONFLICT (modify/delete): dir/file-in-the-way" output && | 	test_grep "CONFLICT (modify/delete): dir/file-in-the-way" output && | ||||||
| 	test_grep "Auto-merging dir" output && | 	test_grep "Auto-merging dir" output && | ||||||
| 	if test "$GIT_TEST_MERGE_ALGORITHM" = ort | 	test_grep "moving it to dir~renamed-file-has-no-conflicts instead" output && | ||||||
| 	then |  | ||||||
| 		test_grep "moving it to dir~renamed-file-has-no-conflicts instead" output |  | ||||||
| 	else |  | ||||||
| 		test_grep "Adding as dir~renamed-file-has-no-conflicts instead" output |  | ||||||
| 	fi && |  | ||||||
|  |  | ||||||
| 	test_stdout_line_count = 3 git ls-files -u && | 	test_stdout_line_count = 3 git ls-files -u && | ||||||
| 	test_stdout_line_count = 2 git ls-files -u dir/file-in-the-way && | 	test_stdout_line_count = 2 git ls-files -u dir/file-in-the-way && | ||||||
|  | @ -400,14 +390,7 @@ test_expect_success 'Rename+D/F conflict; renamed file cannot merge and dir in t | ||||||
| 	test_must_fail git merge --strategy=recursive dir-in-way && | 	test_must_fail git merge --strategy=recursive dir-in-way && | ||||||
|  |  | ||||||
| 	test_stdout_line_count = 5 git ls-files -u && | 	test_stdout_line_count = 5 git ls-files -u && | ||||||
| 	if test "$GIT_TEST_MERGE_ALGORITHM" = ort | 	test_stdout_line_count = 3 git ls-files -u dir~HEAD && | ||||||
| 	then |  | ||||||
| 		test_stdout_line_count = 3 git ls-files -u dir~HEAD |  | ||||||
| 	else |  | ||||||
| 		git ls-files -u dir >out && |  | ||||||
| 		test 3 -eq $(grep -v file-in-the-way out | wc -l) && |  | ||||||
| 		rm -f out |  | ||||||
| 	fi && |  | ||||||
| 	test_stdout_line_count = 2 git ls-files -u dir/file-in-the-way && | 	test_stdout_line_count = 2 git ls-files -u dir/file-in-the-way && | ||||||
|  |  | ||||||
| 	test_must_fail git diff --quiet && | 	test_must_fail git diff --quiet && | ||||||
|  | @ -425,14 +408,7 @@ test_expect_success 'Same as previous, but merged other way' ' | ||||||
| 	test_must_fail git merge --strategy=recursive renamed-file-has-conflicts && | 	test_must_fail git merge --strategy=recursive renamed-file-has-conflicts && | ||||||
|  |  | ||||||
| 	test_stdout_line_count = 5 git ls-files -u && | 	test_stdout_line_count = 5 git ls-files -u && | ||||||
| 	if test "$GIT_TEST_MERGE_ALGORITHM" = ort | 	test_stdout_line_count = 3 git ls-files -u dir~renamed-file-has-conflicts && | ||||||
| 	then |  | ||||||
| 		test_stdout_line_count = 3 git ls-files -u dir~renamed-file-has-conflicts |  | ||||||
| 	else |  | ||||||
| 		git ls-files -u dir >out && |  | ||||||
| 		test 3 -eq $(grep -v file-in-the-way out | wc -l) && |  | ||||||
| 		rm -f out |  | ||||||
| 	fi && |  | ||||||
| 	test_stdout_line_count = 2 git ls-files -u dir/file-in-the-way && | 	test_stdout_line_count = 2 git ls-files -u dir/file-in-the-way && | ||||||
|  |  | ||||||
| 	test_must_fail git diff --quiet && | 	test_must_fail git diff --quiet && | ||||||
|  | @ -488,12 +464,7 @@ test_expect_success 'both rename source and destination involved in D/F conflict | ||||||
| 	git checkout -q rename-dest^0 && | 	git checkout -q rename-dest^0 && | ||||||
| 	test_must_fail git merge --strategy=recursive source-conflict && | 	test_must_fail git merge --strategy=recursive source-conflict && | ||||||
|  |  | ||||||
| 	if test "$GIT_TEST_MERGE_ALGORITHM" = ort | 	test_stdout_line_count = 2 git ls-files -u && | ||||||
| 	then |  | ||||||
| 		test_stdout_line_count = 2 git ls-files -u |  | ||||||
| 	else |  | ||||||
| 		test_stdout_line_count = 1 git ls-files -u |  | ||||||
| 	fi && |  | ||||||
|  |  | ||||||
| 	test_must_fail git diff --quiet && | 	test_must_fail git diff --quiet && | ||||||
|  |  | ||||||
|  | @ -527,9 +498,7 @@ test_expect_success 'setup pair rename to parent of other (D/F conflicts)' ' | ||||||
| 	git commit -m "Rename one/file -> two" | 	git commit -m "Rename one/file -> two" | ||||||
| ' | ' | ||||||
|  |  | ||||||
| if test "$GIT_TEST_MERGE_ALGORITHM" = ort | test_expect_success 'pair rename to parent of other (D/F conflicts) w/ untracked dir' ' | ||||||
| then |  | ||||||
| 	test_expect_success 'pair rename to parent of other (D/F conflicts) w/ untracked dir' ' |  | ||||||
| 	git checkout -q rename-one^0 && | 	git checkout -q rename-one^0 && | ||||||
| 	mkdir one && | 	mkdir one && | ||||||
| 	test_must_fail git merge --strategy=recursive rename-two && | 	test_must_fail git merge --strategy=recursive rename-two && | ||||||
|  | @ -546,44 +515,16 @@ then | ||||||
| 	test_path_is_file two && | 	test_path_is_file two && | ||||||
| 	test "other" = $(cat one) && | 	test "other" = $(cat one) && | ||||||
| 	test "stuff" = $(cat two) | 	test "stuff" = $(cat two) | ||||||
| 	' | ' | ||||||
| else |  | ||||||
| 	test_expect_success 'pair rename to parent of other (D/F conflicts) w/ untracked dir' ' |  | ||||||
| 		git checkout -q rename-one^0 && |  | ||||||
| 		mkdir one && |  | ||||||
| 		test_must_fail git merge --strategy=recursive rename-two && |  | ||||||
|  |  | ||||||
| 		test_stdout_line_count = 2 git ls-files -u && |  | ||||||
| 		test_stdout_line_count = 1 git ls-files -u one && |  | ||||||
| 		test_stdout_line_count = 1 git ls-files -u two && |  | ||||||
|  |  | ||||||
| 		test_must_fail git diff --quiet && |  | ||||||
|  |  | ||||||
| 		test 4 -eq $(find . | grep -v .git | wc -l) && |  | ||||||
|  |  | ||||||
| 		test_path_is_dir one && |  | ||||||
| 		test_path_is_file one~rename-two && |  | ||||||
| 		test_path_is_file two && |  | ||||||
| 		test "other" = $(cat one~rename-two) && |  | ||||||
| 		test "stuff" = $(cat two) |  | ||||||
| 	' |  | ||||||
| fi |  | ||||||
|  |  | ||||||
| test_expect_success 'pair rename to parent of other (D/F conflicts) w/ clean start' ' | test_expect_success 'pair rename to parent of other (D/F conflicts) w/ clean start' ' | ||||||
| 	git reset --hard && | 	git reset --hard && | ||||||
| 	git clean -fdqx && | 	git clean -fdqx && | ||||||
| 	test_must_fail git merge --strategy=recursive rename-two && | 	test_must_fail git merge --strategy=recursive rename-two && | ||||||
|  |  | ||||||
| 	if test "$GIT_TEST_MERGE_ALGORITHM" = ort |  | ||||||
| 	then |  | ||||||
| 	test_stdout_line_count = 4 git ls-files -u && | 	test_stdout_line_count = 4 git ls-files -u && | ||||||
| 	test_stdout_line_count = 2 git ls-files -u one && | 	test_stdout_line_count = 2 git ls-files -u one && | ||||||
| 		test_stdout_line_count = 2 git ls-files -u two | 	test_stdout_line_count = 2 git ls-files -u two && | ||||||
| 	else |  | ||||||
| 		test_stdout_line_count = 2 git ls-files -u && |  | ||||||
| 		test_stdout_line_count = 1 git ls-files -u one && |  | ||||||
| 		test_stdout_line_count = 1 git ls-files -u two |  | ||||||
| 	fi && |  | ||||||
|  |  | ||||||
| 	test_must_fail git diff --quiet && | 	test_must_fail git diff --quiet && | ||||||
|  |  | ||||||
|  | @ -623,22 +564,12 @@ test_expect_success 'check handling of differently renamed file with D/F conflic | ||||||
| 	git checkout -q first-rename^0 && | 	git checkout -q first-rename^0 && | ||||||
| 	test_must_fail git merge --strategy=recursive second-rename && | 	test_must_fail git merge --strategy=recursive second-rename && | ||||||
|  |  | ||||||
| 	if test "$GIT_TEST_MERGE_ALGORITHM" = ort |  | ||||||
| 	then |  | ||||||
| 	test_stdout_line_count = 5 git ls-files -s && | 	test_stdout_line_count = 5 git ls-files -s && | ||||||
| 	test_stdout_line_count = 3 git ls-files -u && | 	test_stdout_line_count = 3 git ls-files -u && | ||||||
| 	test_stdout_line_count = 1 git ls-files -u one~HEAD && | 	test_stdout_line_count = 1 git ls-files -u one~HEAD && | ||||||
| 	test_stdout_line_count = 1 git ls-files -u two~second-rename && | 	test_stdout_line_count = 1 git ls-files -u two~second-rename && | ||||||
| 	test_stdout_line_count = 1 git ls-files -u original && | 	test_stdout_line_count = 1 git ls-files -u original && | ||||||
| 		test_stdout_line_count = 0 git ls-files -o | 	test_stdout_line_count = 0 git ls-files -o && | ||||||
| 	else |  | ||||||
| 		test_stdout_line_count = 5 git ls-files -s && |  | ||||||
| 		test_stdout_line_count = 3 git ls-files -u && |  | ||||||
| 		test_stdout_line_count = 1 git ls-files -u one && |  | ||||||
| 		test_stdout_line_count = 1 git ls-files -u two && |  | ||||||
| 		test_stdout_line_count = 1 git ls-files -u original && |  | ||||||
| 		test_stdout_line_count = 2 git ls-files -o |  | ||||||
| 	fi && |  | ||||||
|  |  | ||||||
| 	test_path_is_file one/file && | 	test_path_is_file one/file && | ||||||
| 	test_path_is_file two/file && | 	test_path_is_file two/file && | ||||||
|  |  | ||||||
|  | @ -108,12 +108,7 @@ test_expect_success 'refuse to merge binary files' ' | ||||||
| 	printf "\0\0" >binary-file && | 	printf "\0\0" >binary-file && | ||||||
| 	git add binary-file && | 	git add binary-file && | ||||||
| 	git commit -m binary2 && | 	git commit -m binary2 && | ||||||
| 	if test "$GIT_TEST_MERGE_ALGORITHM" = ort | 	test_must_fail git merge F >merge_output && | ||||||
| 	then |  | ||||||
| 		test_must_fail git merge F >merge_output |  | ||||||
| 	else |  | ||||||
| 		test_must_fail git merge F 2>merge_output |  | ||||||
| 	fi && |  | ||||||
| 	grep "Cannot merge binary files: binary-file (HEAD vs. F)" merge_output | 	grep "Cannot merge binary files: binary-file (HEAD vs. F)" merge_output | ||||||
| ' | ' | ||||||
|  |  | ||||||
|  | @ -129,22 +124,12 @@ test_expect_success 'mark rename/delete as unmerged' ' | ||||||
| 	test_tick && | 	test_tick && | ||||||
| 	git commit -m rename && | 	git commit -m rename && | ||||||
| 	test_must_fail git merge delete && | 	test_must_fail git merge delete && | ||||||
| 	if test "$GIT_TEST_MERGE_ALGORITHM" = ort | 	test 2 = $(git ls-files --unmerged | wc -l) && | ||||||
| 	then |  | ||||||
| 		test 2 = $(git ls-files --unmerged | wc -l) |  | ||||||
| 	else |  | ||||||
| 		test 1 = $(git ls-files --unmerged | wc -l) |  | ||||||
| 	fi && |  | ||||||
| 	git rev-parse --verify :2:a2 && | 	git rev-parse --verify :2:a2 && | ||||||
| 	test_must_fail git rev-parse --verify :3:a2 && | 	test_must_fail git rev-parse --verify :3:a2 && | ||||||
| 	git checkout -f delete && | 	git checkout -f delete && | ||||||
| 	test_must_fail git merge rename && | 	test_must_fail git merge rename && | ||||||
| 	if test "$GIT_TEST_MERGE_ALGORITHM" = ort | 	test 2 = $(git ls-files --unmerged | wc -l) && | ||||||
| 	then |  | ||||||
| 		test 2 = $(git ls-files --unmerged | wc -l) |  | ||||||
| 	else |  | ||||||
| 		test 1 = $(git ls-files --unmerged | wc -l) |  | ||||||
| 	fi && |  | ||||||
| 	test_must_fail git rev-parse --verify :2:a2 && | 	test_must_fail git rev-parse --verify :2:a2 && | ||||||
| 	git rev-parse --verify :3:a2 | 	git rev-parse --verify :3:a2 | ||||||
| ' | ' | ||||||
|  |  | ||||||
|  | @ -259,12 +259,7 @@ test_expect_success 'binary files with union attribute' ' | ||||||
| 	printf "two\0" >bin.txt && | 	printf "two\0" >bin.txt && | ||||||
| 	git commit -am two && | 	git commit -am two && | ||||||
|  |  | ||||||
| 	if test "$GIT_TEST_MERGE_ALGORITHM" = ort | 	test_must_fail git merge bin-main >output && | ||||||
| 	then |  | ||||||
| 		test_must_fail git merge bin-main >output |  | ||||||
| 	else |  | ||||||
| 		test_must_fail git merge bin-main 2>output |  | ||||||
| 	fi && |  | ||||||
| 	grep -i "warning.*cannot merge.*HEAD vs. bin-main" output | 	grep -i "warning.*cannot merge.*HEAD vs. bin-main" output | ||||||
| ' | ' | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @ -6,7 +6,6 @@ GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main | ||||||
| export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME | export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME | ||||||
|  |  | ||||||
| . ./test-lib.sh | . ./test-lib.sh | ||||||
| . "$TEST_DIRECTORY"/lib-merge.sh |  | ||||||
|  |  | ||||||
| # | # | ||||||
| #  L1  L2 | #  L1  L2 | ||||||
|  | @ -529,15 +528,8 @@ test_expect_success 'setup differently handled merges of directory/file conflict | ||||||
|  |  | ||||||
| 		git checkout B^0 && | 		git checkout B^0 && | ||||||
| 		test_must_fail git merge C^0 && | 		test_must_fail git merge C^0 && | ||||||
| 		if test "$GIT_TEST_MERGE_ALGORITHM" = ort |  | ||||||
| 		then |  | ||||||
| 		git rm -rf a/ && | 		git rm -rf a/ && | ||||||
| 			git rm a~HEAD | 		git rm a~HEAD && | ||||||
| 		else |  | ||||||
| 			git clean -fd && |  | ||||||
| 			git rm -rf a/ && |  | ||||||
| 			git rm a |  | ||||||
| 		fi && |  | ||||||
| 		git cat-file -p B:a >a2 && | 		git cat-file -p B:a >a2 && | ||||||
| 		git add a2 && | 		git add a2 && | ||||||
| 		git commit -m D2 && | 		git commit -m D2 && | ||||||
|  | @ -556,12 +548,7 @@ test_expect_success 'setup differently handled merges of directory/file conflict | ||||||
|  |  | ||||||
| 		git checkout C^0 && | 		git checkout C^0 && | ||||||
| 		test_must_fail git merge B^0 && | 		test_must_fail git merge B^0 && | ||||||
| 		if test "$GIT_TEST_MERGE_ALGORITHM" = ort | 		git rm a~B^0 && | ||||||
| 		then |  | ||||||
| 			git rm a~B^0 |  | ||||||
| 		else |  | ||||||
| 			git clean -fd |  | ||||||
| 		fi && |  | ||||||
| 		git rm -rf a/ && | 		git rm -rf a/ && | ||||||
| 		test_write_lines 1 2 3 4 5 6 7 8 >a && | 		test_write_lines 1 2 3 4 5 6 7 8 >a && | ||||||
| 		git add a && | 		git add a && | ||||||
|  | @ -570,15 +557,8 @@ test_expect_success 'setup differently handled merges of directory/file conflict | ||||||
|  |  | ||||||
| 		git checkout C^0 && | 		git checkout C^0 && | ||||||
| 		test_must_fail git merge B^0 && | 		test_must_fail git merge B^0 && | ||||||
| 		if test "$GIT_TEST_MERGE_ALGORITHM" = ort |  | ||||||
| 		then |  | ||||||
| 		git rm -rf a/ && | 		git rm -rf a/ && | ||||||
| 			git rm a~B^0 | 		git rm a~B^0 && | ||||||
| 		else |  | ||||||
| 			git clean -fd && |  | ||||||
| 			git rm -rf a/ && |  | ||||||
| 			git rm a |  | ||||||
| 		fi && |  | ||||||
| 		test_write_lines 1 2 3 4 5 6 7 8 >a2 && | 		test_write_lines 1 2 3 4 5 6 7 8 >a2 && | ||||||
| 		git add a2 && | 		git add a2 && | ||||||
| 		git commit -m E4 && | 		git commit -m E4 && | ||||||
|  | @ -596,8 +576,6 @@ test_expect_success 'merge of D1 & E1 fails but has appropriate contents' ' | ||||||
|  |  | ||||||
| 		test_must_fail git merge -s recursive E1^0 && | 		test_must_fail git merge -s recursive E1^0 && | ||||||
|  |  | ||||||
| 		if test "$GIT_TEST_MERGE_ALGORITHM" = ort |  | ||||||
| 		then |  | ||||||
| 		git ls-files -s >out && | 		git ls-files -s >out && | ||||||
| 		test_line_count = 3 out && | 		test_line_count = 3 out && | ||||||
| 		git ls-files -u >out && | 		git ls-files -u >out && | ||||||
|  | @ -605,25 +583,9 @@ test_expect_success 'merge of D1 & E1 fails but has appropriate contents' ' | ||||||
| 		git ls-files -o >out && | 		git ls-files -o >out && | ||||||
| 		test_line_count = 1 out && | 		test_line_count = 1 out && | ||||||
|  |  | ||||||
| 			git rev-parse >expect    \ | 		git rev-parse >expect    A:ignore-me  B:a D1:a && | ||||||
| 				A:ignore-me  B:a  D1:a && | 		git rev-parse >actual   :0:ignore-me :1:a :2:a && | ||||||
| 			git rev-parse   >actual   \ |  | ||||||
| 				:0:ignore-me :1:a :2:a && |  | ||||||
| 		test_cmp expect actual | 		test_cmp expect actual | ||||||
| 		else |  | ||||||
| 			git ls-files -s >out && |  | ||||||
| 			test_line_count = 2 out && |  | ||||||
| 			git ls-files -u >out && |  | ||||||
| 			test_line_count = 1 out && |  | ||||||
| 			git ls-files -o >out && |  | ||||||
| 			test_line_count = 1 out && |  | ||||||
|  |  | ||||||
| 			git rev-parse >expect    \ |  | ||||||
| 				A:ignore-me  B:a && |  | ||||||
| 			git rev-parse   >actual   \ |  | ||||||
| 				:0:ignore-me :2:a && |  | ||||||
| 			test_cmp expect actual |  | ||||||
| 		fi |  | ||||||
| 	) | 	) | ||||||
| ' | ' | ||||||
|  |  | ||||||
|  | @ -637,8 +599,6 @@ test_expect_success 'merge of E1 & D1 fails but has appropriate contents' ' | ||||||
|  |  | ||||||
| 		test_must_fail git merge -s recursive D1^0 && | 		test_must_fail git merge -s recursive D1^0 && | ||||||
|  |  | ||||||
| 		if test "$GIT_TEST_MERGE_ALGORITHM" = ort |  | ||||||
| 		then |  | ||||||
| 		git ls-files -s >out && | 		git ls-files -s >out && | ||||||
| 		test_line_count = 3 out && | 		test_line_count = 3 out && | ||||||
| 		git ls-files -u >out && | 		git ls-files -u >out && | ||||||
|  | @ -651,20 +611,6 @@ test_expect_success 'merge of E1 & D1 fails but has appropriate contents' ' | ||||||
| 		git rev-parse   >actual   \ | 		git rev-parse   >actual   \ | ||||||
| 			:0:ignore-me :1:a :3:a && | 			:0:ignore-me :1:a :3:a && | ||||||
| 		test_cmp expect actual | 		test_cmp expect actual | ||||||
| 		else |  | ||||||
| 			git ls-files -s >out && |  | ||||||
| 			test_line_count = 2 out && |  | ||||||
| 			git ls-files -u >out && |  | ||||||
| 			test_line_count = 1 out && |  | ||||||
| 			git ls-files -o >out && |  | ||||||
| 			test_line_count = 1 out && |  | ||||||
|  |  | ||||||
| 			git rev-parse >expect    \ |  | ||||||
| 				A:ignore-me  B:a && |  | ||||||
| 			git rev-parse   >actual   \ |  | ||||||
| 				:0:ignore-me :3:a && |  | ||||||
| 			test_cmp expect actual |  | ||||||
| 		fi |  | ||||||
| 	) | 	) | ||||||
| ' | ' | ||||||
|  |  | ||||||
|  | @ -678,8 +624,6 @@ test_expect_success 'merge of D1 & E2 fails but has appropriate contents' ' | ||||||
|  |  | ||||||
| 		test_must_fail git merge -s recursive E2^0 && | 		test_must_fail git merge -s recursive E2^0 && | ||||||
|  |  | ||||||
| 		if test "$GIT_TEST_MERGE_ALGORITHM" = ort |  | ||||||
| 		then |  | ||||||
| 		git ls-files -s >out && | 		git ls-files -s >out && | ||||||
| 		test_line_count = 5 out && | 		test_line_count = 5 out && | ||||||
| 		git ls-files -u >out && | 		git ls-files -u >out && | ||||||
|  | @ -690,20 +634,7 @@ test_expect_success 'merge of D1 & E2 fails but has appropriate contents' ' | ||||||
| 		git rev-parse >expect    \ | 		git rev-parse >expect    \ | ||||||
| 			B:a       D1:a      E2:a/file  C:a/file   A:ignore-me && | 			B:a       D1:a      E2:a/file  C:a/file   A:ignore-me && | ||||||
| 		git rev-parse   >actual   \ | 		git rev-parse   >actual   \ | ||||||
| 				:1:a~HEAD :2:a~HEAD :3:a/file  :1:a/file  :0:ignore-me | 			:1:a~HEAD :2:a~HEAD :3:a/file  :1:a/file  :0:ignore-me && | ||||||
| 		else |  | ||||||
| 			git ls-files -s >out && |  | ||||||
| 			test_line_count = 4 out && |  | ||||||
| 			git ls-files -u >out && |  | ||||||
| 			test_line_count = 3 out && |  | ||||||
| 			git ls-files -o >out && |  | ||||||
| 			test_line_count = 2 out && |  | ||||||
|  |  | ||||||
| 			git rev-parse >expect    \ |  | ||||||
| 				B:a    E2:a/file  C:a/file   A:ignore-me && |  | ||||||
| 			git rev-parse   >actual   \ |  | ||||||
| 				:2:a   :3:a/file  :1:a/file  :0:ignore-me |  | ||||||
| 		fi && |  | ||||||
| 		test_cmp expect actual && | 		test_cmp expect actual && | ||||||
|  |  | ||||||
| 		test_path_is_file a~HEAD | 		test_path_is_file a~HEAD | ||||||
|  | @ -720,8 +651,6 @@ test_expect_success 'merge of E2 & D1 fails but has appropriate contents' ' | ||||||
|  |  | ||||||
| 		test_must_fail git merge -s recursive D1^0 && | 		test_must_fail git merge -s recursive D1^0 && | ||||||
|  |  | ||||||
| 		if test "$GIT_TEST_MERGE_ALGORITHM" = ort |  | ||||||
| 		then |  | ||||||
| 		git ls-files -s >out && | 		git ls-files -s >out && | ||||||
| 		test_line_count = 5 out && | 		test_line_count = 5 out && | ||||||
| 		git ls-files -u >out && | 		git ls-files -u >out && | ||||||
|  | @ -732,20 +661,7 @@ test_expect_success 'merge of E2 & D1 fails but has appropriate contents' ' | ||||||
| 		git rev-parse >expect    \ | 		git rev-parse >expect    \ | ||||||
| 			B:a       D1:a      E2:a/file  C:a/file   A:ignore-me && | 			B:a       D1:a      E2:a/file  C:a/file   A:ignore-me && | ||||||
| 		git rev-parse   >actual   \ | 		git rev-parse   >actual   \ | ||||||
| 				:1:a~D1^0 :3:a~D1^0 :2:a/file  :1:a/file  :0:ignore-me | 			:1:a~D1^0 :3:a~D1^0 :2:a/file  :1:a/file  :0:ignore-me && | ||||||
| 		else |  | ||||||
| 			git ls-files -s >out && |  | ||||||
| 			test_line_count = 4 out && |  | ||||||
| 			git ls-files -u >out && |  | ||||||
| 			test_line_count = 3 out && |  | ||||||
| 			git ls-files -o >out && |  | ||||||
| 			test_line_count = 2 out && |  | ||||||
|  |  | ||||||
| 			git rev-parse >expect    \ |  | ||||||
| 				B:a   E2:a/file  C:a/file   A:ignore-me && |  | ||||||
| 			git rev-parse   >actual   \ |  | ||||||
| 				:3:a  :2:a/file  :1:a/file  :0:ignore-me |  | ||||||
| 		fi && |  | ||||||
| 		test_cmp expect actual && | 		test_cmp expect actual && | ||||||
|  |  | ||||||
| 		test_path_is_file a~D1^0 | 		test_path_is_file a~D1^0 | ||||||
|  | @ -777,7 +693,7 @@ test_expect_success 'merge of D1 & E3 succeeds' ' | ||||||
| 	) | 	) | ||||||
| ' | ' | ||||||
|  |  | ||||||
| test_expect_merge_algorithm failure success 'merge of D1 & E4 puts merge of a and a2 in both a and a2' ' | test_expect_success 'merge of D1 & E4 puts merge of a and a2 in both a and a2' ' | ||||||
| 	test_when_finished "git -C directory-file reset --hard" && | 	test_when_finished "git -C directory-file reset --hard" && | ||||||
| 	test_when_finished "git -C directory-file clean -fdqx" && | 	test_when_finished "git -C directory-file clean -fdqx" && | ||||||
| 	( | 	( | ||||||
|  | @ -1140,7 +1056,7 @@ test_expect_success 'setup symlink modify/modify' ' | ||||||
| 	) | 	) | ||||||
| ' | ' | ||||||
|  |  | ||||||
| test_expect_merge_algorithm failure success 'check symlink modify/modify' ' | test_expect_success 'check symlink modify/modify' ' | ||||||
| 	( | 	( | ||||||
| 		cd symlink-modify-modify && | 		cd symlink-modify-modify && | ||||||
|  |  | ||||||
|  | @ -1206,7 +1122,7 @@ test_expect_success 'setup symlink add/add' ' | ||||||
| 	) | 	) | ||||||
| ' | ' | ||||||
|  |  | ||||||
| test_expect_merge_algorithm failure success 'check symlink add/add' ' | test_expect_success 'check symlink add/add' ' | ||||||
| 	( | 	( | ||||||
| 		cd symlink-add-add && | 		cd symlink-add-add && | ||||||
|  |  | ||||||
|  | @ -1294,7 +1210,7 @@ test_expect_success 'setup submodule modify/modify' ' | ||||||
| 	) | 	) | ||||||
| ' | ' | ||||||
|  |  | ||||||
| test_expect_merge_algorithm failure success 'check submodule modify/modify' ' | test_expect_success 'check submodule modify/modify' ' | ||||||
| 	( | 	( | ||||||
| 		cd submodule-modify-modify && | 		cd submodule-modify-modify && | ||||||
|  |  | ||||||
|  | @ -1382,7 +1298,7 @@ test_expect_success 'setup submodule add/add' ' | ||||||
| 	) | 	) | ||||||
| ' | ' | ||||||
|  |  | ||||||
| test_expect_merge_algorithm failure success 'check submodule add/add' ' | test_expect_success 'check submodule add/add' ' | ||||||
| 	( | 	( | ||||||
| 		cd submodule-add-add && | 		cd submodule-add-add && | ||||||
|  |  | ||||||
|  | @ -1457,7 +1373,7 @@ test_expect_success 'setup conflicting entry types (submodule vs symlink)' ' | ||||||
| 	) | 	) | ||||||
| ' | ' | ||||||
|  |  | ||||||
| test_expect_merge_algorithm failure success 'check conflicting entry types (submodule vs symlink)' ' | test_expect_success 'check conflicting entry types (submodule vs symlink)' ' | ||||||
| 	( | 	( | ||||||
| 		cd submodule-symlink-add-add && | 		cd submodule-symlink-add-add && | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @ -27,7 +27,6 @@ test_description="limiting blob downloads when merging with partial clones" | ||||||
| #                     files that might be renamed into each other's paths.) | #                     files that might be renamed into each other's paths.) | ||||||
|  |  | ||||||
| . ./test-lib.sh | . ./test-lib.sh | ||||||
| . "$TEST_DIRECTORY"/lib-merge.sh |  | ||||||
|  |  | ||||||
| test_setup_repo () { | test_setup_repo () { | ||||||
| 	test -d server && return | 	test -d server && return | ||||||
|  | @ -207,7 +206,7 @@ test_setup_repo () { | ||||||
| # | # | ||||||
| #   Summary: 2 fetches (1 for 2 objects, 1 for 1 object) | #   Summary: 2 fetches (1 for 2 objects, 1 for 1 object) | ||||||
| # | # | ||||||
| test_expect_merge_algorithm failure success 'Objects downloaded for single relevant rename' ' | test_expect_success 'Objects downloaded for single relevant rename' ' | ||||||
| 	test_setup_repo && | 	test_setup_repo && | ||||||
| 	git clone --sparse --filter=blob:none "file://$(pwd)/server" objects-single && | 	git clone --sparse --filter=blob:none "file://$(pwd)/server" objects-single && | ||||||
| 	( | 	( | ||||||
|  | @ -297,7 +296,7 @@ test_expect_merge_algorithm failure success 'Objects downloaded for single relev | ||||||
| #      this are not all that common.) | #      this are not all that common.) | ||||||
| #   Summary: 1 fetches for 6 objects | #   Summary: 1 fetches for 6 objects | ||||||
| # | # | ||||||
| test_expect_merge_algorithm failure success 'Objects downloaded when a directory rename triggered' ' | test_expect_success 'Objects downloaded when a directory rename triggered' ' | ||||||
| 	test_setup_repo && | 	test_setup_repo && | ||||||
| 	git clone --sparse --filter=blob:none "file://$(pwd)/server" objects-dir && | 	git clone --sparse --filter=blob:none "file://$(pwd)/server" objects-dir && | ||||||
| 	( | 	( | ||||||
|  | @ -399,7 +398,7 @@ test_expect_merge_algorithm failure success 'Objects downloaded when a directory | ||||||
| # | # | ||||||
| #   Summary: 4 fetches (1 for 6 objects, 1 for 8, 1 for 3, 1 for 2) | #   Summary: 4 fetches (1 for 6 objects, 1 for 8, 1 for 3, 1 for 2) | ||||||
| # | # | ||||||
| test_expect_merge_algorithm failure success 'Objects downloaded with lots of renames and modifications' ' | test_expect_success 'Objects downloaded with lots of renames and modifications' ' | ||||||
| 	test_setup_repo && | 	test_setup_repo && | ||||||
| 	git clone --sparse --filter=blob:none "file://$(pwd)/server" objects-many && | 	git clone --sparse --filter=blob:none "file://$(pwd)/server" objects-many && | ||||||
| 	( | 	( | ||||||
|  |  | ||||||
|  | @ -7,7 +7,6 @@ GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main | ||||||
| export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME | export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME | ||||||
|  |  | ||||||
| . ./test-lib.sh | . ./test-lib.sh | ||||||
| . "$TEST_DIRECTORY"/lib-merge.sh |  | ||||||
|  |  | ||||||
| test_setup_rename_delete_untracked () { | test_setup_rename_delete_untracked () { | ||||||
| 	git init rename-delete-untracked && | 	git init rename-delete-untracked && | ||||||
|  | @ -316,12 +315,7 @@ test_expect_success 'rename/directory conflict + clean content merge' ' | ||||||
| 		git ls-files -u >out && | 		git ls-files -u >out && | ||||||
| 		test_line_count = 1 out && | 		test_line_count = 1 out && | ||||||
| 		git ls-files -o >out && | 		git ls-files -o >out && | ||||||
| 		if test "$GIT_TEST_MERGE_ALGORITHM" = ort | 		test_line_count = 1 out && | ||||||
| 		then |  | ||||||
| 			test_line_count = 1 out |  | ||||||
| 		else |  | ||||||
| 			test_line_count = 2 out |  | ||||||
| 		fi && |  | ||||||
|  |  | ||||||
| 		echo 0 >expect && | 		echo 0 >expect && | ||||||
| 		git cat-file -p base:file >>expect && | 		git cat-file -p base:file >>expect && | ||||||
|  | @ -350,12 +344,7 @@ test_expect_success 'rename/directory conflict + content merge conflict' ' | ||||||
| 		git ls-files -u >out && | 		git ls-files -u >out && | ||||||
| 		test_line_count = 3 out && | 		test_line_count = 3 out && | ||||||
| 		git ls-files -o >out && | 		git ls-files -o >out && | ||||||
| 		if test "$GIT_TEST_MERGE_ALGORITHM" = ort | 		test_line_count = 1 out && | ||||||
| 		then |  | ||||||
| 			test_line_count = 1 out |  | ||||||
| 		else |  | ||||||
| 			test_line_count = 2 out |  | ||||||
| 		fi && |  | ||||||
|  |  | ||||||
| 		git cat-file -p left-conflict:newfile >left && | 		git cat-file -p left-conflict:newfile >left && | ||||||
| 		git cat-file -p base:file    >base && | 		git cat-file -p base:file    >base && | ||||||
|  | @ -369,14 +358,8 @@ test_expect_success 'rename/directory conflict + content merge conflict' ' | ||||||
|  |  | ||||||
| 		git rev-parse >expect   \ | 		git rev-parse >expect   \ | ||||||
| 			base:file       left-conflict:newfile right:file && | 			base:file       left-conflict:newfile right:file && | ||||||
| 		if test "$GIT_TEST_MERGE_ALGORITHM" = ort |  | ||||||
| 		then |  | ||||||
| 		git rev-parse >actual \ | 		git rev-parse >actual \ | ||||||
| 				:1:newfile~HEAD :2:newfile~HEAD :3:newfile~HEAD | 			:1:newfile~HEAD :2:newfile~HEAD :3:newfile~HEAD && | ||||||
| 		else |  | ||||||
| 			git rev-parse >actual \ |  | ||||||
| 				:1:newfile      :2:newfile      :3:newfile |  | ||||||
| 		fi && |  | ||||||
| 		test_cmp expect actual && | 		test_cmp expect actual && | ||||||
|  |  | ||||||
| 		test_path_is_file newfile/realfile && | 		test_path_is_file newfile/realfile && | ||||||
|  | @ -896,7 +879,7 @@ test_setup_rad () { | ||||||
| 	) | 	) | ||||||
| } | } | ||||||
|  |  | ||||||
| test_expect_merge_algorithm failure success 'rad-check: rename/add/delete conflict' ' | test_expect_success 'rad-check: rename/add/delete conflict' ' | ||||||
| 	test_setup_rad && | 	test_setup_rad && | ||||||
| 	( | 	( | ||||||
| 		cd rad && | 		cd rad && | ||||||
|  | @ -969,7 +952,7 @@ test_setup_rrdd () { | ||||||
| 	) | 	) | ||||||
| } | } | ||||||
|  |  | ||||||
| test_expect_merge_algorithm failure success 'rrdd-check: rename/rename(2to1)/delete/delete conflict' ' | test_expect_success 'rrdd-check: rename/rename(2to1)/delete/delete conflict' ' | ||||||
| 	test_setup_rrdd && | 	test_setup_rrdd && | ||||||
| 	( | 	( | ||||||
| 		cd rrdd && | 		cd rrdd && | ||||||
|  | @ -1058,7 +1041,7 @@ test_setup_mod6 () { | ||||||
| 	) | 	) | ||||||
| } | } | ||||||
|  |  | ||||||
| test_expect_merge_algorithm failure success 'mod6-check: chains of rename/rename(1to2) and rename/rename(2to1)' ' | test_expect_success 'mod6-check: chains of rename/rename(1to2) and rename/rename(2to1)' ' | ||||||
| 	test_setup_mod6 && | 	test_setup_mod6 && | ||||||
| 	( | 	( | ||||||
| 		cd mod6 && | 		cd mod6 && | ||||||
|  |  | ||||||
|  | @ -26,8 +26,6 @@ test_description="recursive merge with directory renames" | ||||||
| #                     files that might be renamed into each other's paths.) | #                     files that might be renamed into each other's paths.) | ||||||
|  |  | ||||||
| . ./test-lib.sh | . ./test-lib.sh | ||||||
| . "$TEST_DIRECTORY"/lib-merge.sh |  | ||||||
|  |  | ||||||
|  |  | ||||||
| ########################################################################### | ########################################################################### | ||||||
| # SECTION 1: Basic cases we should be able to handle | # SECTION 1: Basic cases we should be able to handle | ||||||
|  | @ -302,20 +300,11 @@ test_expect_success '1d: Directory renames cause a rename/rename(2to1) conflict' | ||||||
| 		git cat-file -p :2:x/wham >expect && | 		git cat-file -p :2:x/wham >expect && | ||||||
| 		git cat-file -p :3:x/wham >other && | 		git cat-file -p :3:x/wham >other && | ||||||
| 		>empty && | 		>empty && | ||||||
| 		if test "$GIT_TEST_MERGE_ALGORITHM" = ort |  | ||||||
| 		then |  | ||||||
| 		test_must_fail git merge-file \ | 		test_must_fail git merge-file \ | ||||||
| 			-L "HEAD:y/wham" \ | 			-L "HEAD:y/wham" \ | ||||||
| 			-L "" \ | 			-L "" \ | ||||||
| 			-L "B^0:z/wham" \ | 			-L "B^0:z/wham" \ | ||||||
| 				expect empty other | 			expect empty other && | ||||||
| 		else |  | ||||||
| 			test_must_fail git merge-file \ |  | ||||||
| 				-L "HEAD" \ |  | ||||||
| 				-L "" \ |  | ||||||
| 				-L "B^0" \ |  | ||||||
| 				expect empty other |  | ||||||
| 		fi && |  | ||||||
| 		test_cmp expect x/wham | 		test_cmp expect x/wham | ||||||
| 	) | 	) | ||||||
| ' | ' | ||||||
|  | @ -1186,18 +1175,10 @@ test_expect_success '5d: Directory/file/file conflict due to directory rename' ' | ||||||
| 		git ls-files -u >out && | 		git ls-files -u >out && | ||||||
| 		test_line_count = 1 out && | 		test_line_count = 1 out && | ||||||
| 		git ls-files -o >out && | 		git ls-files -o >out && | ||||||
| 		if test "$GIT_TEST_MERGE_ALGORITHM" = ort |  | ||||||
| 		then |  | ||||||
| 		test_line_count = 1 out && | 		test_line_count = 1 out && | ||||||
|  |  | ||||||
| 		git rev-parse >actual \ | 		git rev-parse >actual \ | ||||||
| 			    :0:y/b :0:y/c :0:z/d :0:y/f :2:y/d~HEAD :0:y/d/e | 		    :0:y/b :0:y/c :0:z/d :0:y/f :2:y/d~HEAD :0:y/d/e && | ||||||
| 		else |  | ||||||
| 			test_line_count = 2 out && |  | ||||||
|  |  | ||||||
| 			git rev-parse >actual \ |  | ||||||
| 			    :0:y/b :0:y/c :0:z/d :0:y/f :2:y/d      :0:y/d/e |  | ||||||
| 		fi && |  | ||||||
| 		git rev-parse >expect \ | 		git rev-parse >expect \ | ||||||
| 			 O:z/b  O:z/c  B:z/d  B:z/f  A:y/d  B:y/d/e && | 			 O:z/b  O:z/c  B:z/d  B:z/f  A:y/d  B:y/d/e && | ||||||
| 		test_cmp expect actual && | 		test_cmp expect actual && | ||||||
|  | @ -1280,8 +1261,6 @@ test_expect_success '6a: Tricky rename/delete' ' | ||||||
| 		test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out && | 		test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out && | ||||||
| 		test_grep "CONFLICT (rename/delete).*z/c.*y/c" out && | 		test_grep "CONFLICT (rename/delete).*z/c.*y/c" out && | ||||||
|  |  | ||||||
| 		if test "$GIT_TEST_MERGE_ALGORITHM" = ort |  | ||||||
| 		then |  | ||||||
| 		git ls-files -s >out && | 		git ls-files -s >out && | ||||||
| 		test_line_count = 3 out && | 		test_line_count = 3 out && | ||||||
| 		git ls-files -u >out && | 		git ls-files -u >out && | ||||||
|  | @ -1292,20 +1271,7 @@ test_expect_success '6a: Tricky rename/delete' ' | ||||||
| 		git rev-parse >actual \ | 		git rev-parse >actual \ | ||||||
| 			:0:y/b :1:y/c :3:y/c && | 			:0:y/b :1:y/c :3:y/c && | ||||||
| 		git rev-parse >expect \ | 		git rev-parse >expect \ | ||||||
| 				 O:z/b  O:z/c  O:z/c | 			 O:z/b  O:z/c  O:z/c && | ||||||
| 		else |  | ||||||
| 			git ls-files -s >out && |  | ||||||
| 			test_line_count = 2 out && |  | ||||||
| 			git ls-files -u >out && |  | ||||||
| 			test_line_count = 1 out && |  | ||||||
| 			git ls-files -o >out && |  | ||||||
| 			test_line_count = 1 out && |  | ||||||
|  |  | ||||||
| 			git rev-parse >actual \ |  | ||||||
| 				:0:y/b :3:y/c && |  | ||||||
| 			git rev-parse >expect \ |  | ||||||
| 				 O:z/b  O:z/c |  | ||||||
| 		fi && |  | ||||||
| 		test_cmp expect actual | 		test_cmp expect actual | ||||||
| 	) | 	) | ||||||
| ' | ' | ||||||
|  | @ -1372,7 +1338,7 @@ test_setup_6b1 () { | ||||||
| 	) | 	) | ||||||
| } | } | ||||||
|  |  | ||||||
| test_expect_merge_algorithm failure success '6b1: Same renames done on both sides, plus another rename' ' | test_expect_success '6b1: Same renames done on both sides, plus another rename' ' | ||||||
| 	test_setup_6b1 && | 	test_setup_6b1 && | ||||||
| 	( | 	( | ||||||
| 		cd 6b1 && | 		cd 6b1 && | ||||||
|  | @ -1445,7 +1411,7 @@ test_setup_6b2 () { | ||||||
| 	) | 	) | ||||||
| } | } | ||||||
|  |  | ||||||
| test_expect_merge_algorithm failure success '6b2: Same rename done on both sides' ' | test_expect_success '6b2: Same rename done on both sides' ' | ||||||
| 	test_setup_6b2 && | 	test_setup_6b2 && | ||||||
| 	( | 	( | ||||||
| 		cd 6b2 && | 		cd 6b2 && | ||||||
|  | @ -1832,20 +1798,11 @@ test_expect_success '7b: rename/rename(2to1), but only due to transitive rename' | ||||||
| 		git cat-file -p :2:y/d >expect && | 		git cat-file -p :2:y/d >expect && | ||||||
| 		git cat-file -p :3:y/d >other && | 		git cat-file -p :3:y/d >other && | ||||||
| 		>empty && | 		>empty && | ||||||
| 		if test "$GIT_TEST_MERGE_ALGORITHM" = ort |  | ||||||
| 		then |  | ||||||
| 		test_must_fail git merge-file \ | 		test_must_fail git merge-file \ | ||||||
| 			-L "HEAD:y/d" \ | 			-L "HEAD:y/d" \ | ||||||
| 			-L "" \ | 			-L "" \ | ||||||
| 			-L "B^0:z/d" \ | 			-L "B^0:z/d" \ | ||||||
| 				expect empty other | 			expect empty other && | ||||||
| 		else |  | ||||||
| 			test_must_fail git merge-file \ |  | ||||||
| 				-L "HEAD" \ |  | ||||||
| 				-L "" \ |  | ||||||
| 				-L "B^0" \ |  | ||||||
| 				expect empty other |  | ||||||
| 		fi && |  | ||||||
| 		test_cmp expect y/d | 		test_cmp expect y/d | ||||||
| 	) | 	) | ||||||
| ' | ' | ||||||
|  | @ -1967,8 +1924,6 @@ test_expect_success '7d: transitive rename involved in rename/delete; how is it | ||||||
| 		test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out && | 		test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out && | ||||||
| 		test_grep "CONFLICT (rename/delete).*x/d.*y/d" out && | 		test_grep "CONFLICT (rename/delete).*x/d.*y/d" out && | ||||||
|  |  | ||||||
| 		if test "$GIT_TEST_MERGE_ALGORITHM" = ort |  | ||||||
| 		then |  | ||||||
| 		git ls-files -s >out && | 		git ls-files -s >out && | ||||||
| 		test_line_count = 4 out && | 		test_line_count = 4 out && | ||||||
| 		git ls-files -u >out && | 		git ls-files -u >out && | ||||||
|  | @ -1979,20 +1934,7 @@ test_expect_success '7d: transitive rename involved in rename/delete; how is it | ||||||
| 		git rev-parse >actual \ | 		git rev-parse >actual \ | ||||||
| 			:0:y/b :0:y/c :1:y/d :3:y/d && | 			:0:y/b :0:y/c :1:y/d :3:y/d && | ||||||
| 		git rev-parse >expect \ | 		git rev-parse >expect \ | ||||||
| 				 O:z/b  O:z/c  O:x/d  O:x/d | 			 O:z/b  O:z/c  O:x/d  O:x/d && | ||||||
| 		else |  | ||||||
| 			git ls-files -s >out && |  | ||||||
| 			test_line_count = 3 out && |  | ||||||
| 			git ls-files -u >out && |  | ||||||
| 			test_line_count = 1 out && |  | ||||||
| 			git ls-files -o >out && |  | ||||||
| 			test_line_count = 1 out && |  | ||||||
|  |  | ||||||
| 			git rev-parse >actual \ |  | ||||||
| 				:0:y/b :0:y/c :3:y/d && |  | ||||||
| 			git rev-parse >expect \ |  | ||||||
| 				 O:z/b  O:z/c  O:x/d |  | ||||||
| 		fi && |  | ||||||
| 		test_cmp expect actual | 		test_cmp expect actual | ||||||
| 	) | 	) | ||||||
| ' | ' | ||||||
|  | @ -2073,8 +2015,6 @@ test_expect_success '7e: transitive rename in rename/delete AND dirs in the way' | ||||||
| 		test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out && | 		test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out && | ||||||
| 		test_grep "CONFLICT (rename/delete).*x/d.*y/d" out && | 		test_grep "CONFLICT (rename/delete).*x/d.*y/d" out && | ||||||
|  |  | ||||||
| 		if test "$GIT_TEST_MERGE_ALGORITHM" = ort |  | ||||||
| 		then |  | ||||||
| 		git ls-files -s >out && | 		git ls-files -s >out && | ||||||
| 		test_line_count = 6 out && | 		test_line_count = 6 out && | ||||||
| 		git ls-files -u >out && | 		git ls-files -u >out && | ||||||
|  | @ -2085,20 +2025,7 @@ test_expect_success '7e: transitive rename in rename/delete AND dirs in the way' | ||||||
| 		git rev-parse >actual \ | 		git rev-parse >actual \ | ||||||
| 			:0:x/d/f :0:y/d/g :0:y/b :0:y/c :1:y/d~B^0 :3:y/d~B^0 && | 			:0:x/d/f :0:y/d/g :0:y/b :0:y/c :1:y/d~B^0 :3:y/d~B^0 && | ||||||
| 		git rev-parse >expect \ | 		git rev-parse >expect \ | ||||||
| 				 A:x/d/f  A:y/d/g  O:z/b  O:z/c  O:x/d      O:x/d | 			 A:x/d/f  A:y/d/g  O:z/b  O:z/c  O:x/d      O:x/d && | ||||||
| 		else |  | ||||||
| 			git ls-files -s >out && |  | ||||||
| 			test_line_count = 5 out && |  | ||||||
| 			git ls-files -u >out && |  | ||||||
| 			test_line_count = 1 out && |  | ||||||
| 			git ls-files -o >out && |  | ||||||
| 			test_line_count = 2 out && |  | ||||||
|  |  | ||||||
| 			git rev-parse >actual \ |  | ||||||
| 				:0:x/d/f :0:y/d/g :0:y/b :0:y/c :3:y/d && |  | ||||||
| 			git rev-parse >expect \ |  | ||||||
| 				 A:x/d/f  A:y/d/g  O:z/b  O:z/c  O:x/d |  | ||||||
| 		fi && |  | ||||||
| 		test_cmp expect actual && | 		test_cmp expect actual && | ||||||
|  |  | ||||||
| 		git hash-object y/d~B^0 >actual && | 		git hash-object y/d~B^0 >actual && | ||||||
|  | @ -3284,8 +3211,6 @@ test_expect_success '10b: Overwrite untracked with dir rename + delete' ' | ||||||
| 		echo contents >y/e && | 		echo contents >y/e && | ||||||
|  |  | ||||||
| 		test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && | 		test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && | ||||||
| 		if test "$GIT_TEST_MERGE_ALGORITHM" = ort |  | ||||||
| 		then |  | ||||||
| 		test_path_is_missing .git/MERGE_HEAD && | 		test_path_is_missing .git/MERGE_HEAD && | ||||||
| 		test_grep "error: The following untracked working tree files would be overwritten by merge" err && | 		test_grep "error: The following untracked working tree files would be overwritten by merge" err && | ||||||
|  |  | ||||||
|  | @ -3294,25 +3219,8 @@ test_expect_success '10b: Overwrite untracked with dir rename + delete' ' | ||||||
| 		git ls-files -u >out && | 		git ls-files -u >out && | ||||||
| 		test_line_count = 0 out && | 		test_line_count = 0 out && | ||||||
| 		git ls-files -o >out && | 		git ls-files -o >out && | ||||||
| 			test_line_count = 5 out |  | ||||||
| 		else |  | ||||||
| 			test_grep "CONFLICT (rename/delete).*Version B\^0 of y/d left in tree at y/d~B\^0" out && |  | ||||||
| 			test_grep "Error: Refusing to lose untracked file at y/e; writing to y/e~B\^0 instead" out && |  | ||||||
|  |  | ||||||
| 			git ls-files -s >out && |  | ||||||
| 			test_line_count = 3 out && |  | ||||||
| 			git ls-files -u >out && |  | ||||||
| 			test_line_count = 2 out && |  | ||||||
| 			git ls-files -o >out && |  | ||||||
| 		test_line_count = 5 out && | 		test_line_count = 5 out && | ||||||
|  |  | ||||||
| 			git rev-parse >actual \ |  | ||||||
| 				:0:y/b :3:y/d :3:y/e && |  | ||||||
| 			git rev-parse >expect \ |  | ||||||
| 				O:z/b  O:z/c  B:z/e && |  | ||||||
| 			test_cmp expect actual |  | ||||||
| 		fi && |  | ||||||
|  |  | ||||||
| 		echo very >expect && | 		echo very >expect && | ||||||
| 		test_cmp expect y/c && | 		test_cmp expect y/c && | ||||||
|  |  | ||||||
|  | @ -3374,8 +3282,6 @@ test_expect_success '10c1: Overwrite untracked with dir rename/rename(1to2)' ' | ||||||
| 		echo important >y/c && | 		echo important >y/c && | ||||||
|  |  | ||||||
| 		test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && | 		test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && | ||||||
| 		if test "$GIT_TEST_MERGE_ALGORITHM" = ort |  | ||||||
| 		then |  | ||||||
| 		test_path_is_missing .git/MERGE_HEAD && | 		test_path_is_missing .git/MERGE_HEAD && | ||||||
| 		test_grep "error: The following untracked working tree files would be overwritten by merge" err && | 		test_grep "error: The following untracked working tree files would be overwritten by merge" err && | ||||||
|  |  | ||||||
|  | @ -3384,28 +3290,7 @@ test_expect_success '10c1: Overwrite untracked with dir rename/rename(1to2)' ' | ||||||
| 		git ls-files -u >out && | 		git ls-files -u >out && | ||||||
| 		test_line_count = 0 out && | 		test_line_count = 0 out && | ||||||
| 		git ls-files -o >out && | 		git ls-files -o >out && | ||||||
| 			test_line_count = 3 out |  | ||||||
| 		else |  | ||||||
| 			test_grep "CONFLICT (rename/rename)" out && |  | ||||||
| 			test_grep "Refusing to lose untracked file at y/c; adding as y/c~B\^0 instead" out && |  | ||||||
|  |  | ||||||
| 			git ls-files -s >out && |  | ||||||
| 			test_line_count = 6 out && |  | ||||||
| 			git ls-files -u >out && |  | ||||||
| 		test_line_count = 3 out && | 		test_line_count = 3 out && | ||||||
| 			git ls-files -o >out && |  | ||||||
| 			test_line_count = 3 out && |  | ||||||
|  |  | ||||||
| 			git rev-parse >actual \ |  | ||||||
| 				:0:y/a :0:y/b :0:x/d :1:x/c :2:w/c :3:y/c && |  | ||||||
| 			git rev-parse >expect \ |  | ||||||
| 				 O:z/a  O:z/b  O:x/d  O:x/c  O:x/c  O:x/c && |  | ||||||
| 			test_cmp expect actual && |  | ||||||
|  |  | ||||||
| 			git hash-object y/c~B^0 >actual && |  | ||||||
| 			git rev-parse O:x/c >expect && |  | ||||||
| 			test_cmp expect actual |  | ||||||
| 		fi && |  | ||||||
|  |  | ||||||
| 		echo important >expect && | 		echo important >expect && | ||||||
| 		test_cmp expect y/c | 		test_cmp expect y/c | ||||||
|  | @ -3425,8 +3310,6 @@ test_expect_success '10c2: Overwrite untracked with dir rename/rename(1to2), oth | ||||||
| 		echo important >y/c && | 		echo important >y/c && | ||||||
|  |  | ||||||
| 		test_must_fail git -c merge.directoryRenames=true merge -s recursive A^0 >out 2>err && | 		test_must_fail git -c merge.directoryRenames=true merge -s recursive A^0 >out 2>err && | ||||||
| 		if test "$GIT_TEST_MERGE_ALGORITHM" = ort |  | ||||||
| 		then |  | ||||||
| 		test_path_is_missing .git/MERGE_HEAD && | 		test_path_is_missing .git/MERGE_HEAD && | ||||||
| 		test_grep "error: The following untracked working tree files would be overwritten by merge" err && | 		test_grep "error: The following untracked working tree files would be overwritten by merge" err && | ||||||
|  |  | ||||||
|  | @ -3435,28 +3318,7 @@ test_expect_success '10c2: Overwrite untracked with dir rename/rename(1to2), oth | ||||||
| 		git ls-files -u >out && | 		git ls-files -u >out && | ||||||
| 		test_line_count = 0 out && | 		test_line_count = 0 out && | ||||||
| 		git ls-files -o >out && | 		git ls-files -o >out && | ||||||
| 			test_line_count = 3 out |  | ||||||
| 		else |  | ||||||
| 			test_grep "CONFLICT (rename/rename)" out && |  | ||||||
| 			test_grep "Refusing to lose untracked file at y/c; adding as y/c~HEAD instead" out && |  | ||||||
|  |  | ||||||
| 			git ls-files -s >out && |  | ||||||
| 			test_line_count = 6 out && |  | ||||||
| 			git ls-files -u >out && |  | ||||||
| 		test_line_count = 3 out && | 		test_line_count = 3 out && | ||||||
| 			git ls-files -o >out && |  | ||||||
| 			test_line_count = 3 out && |  | ||||||
|  |  | ||||||
| 			git rev-parse >actual \ |  | ||||||
| 				:0:y/a :0:y/b :0:x/d :1:x/c :3:w/c :2:y/c && |  | ||||||
| 			git rev-parse >expect \ |  | ||||||
| 				 O:z/a  O:z/b  O:x/d  O:x/c  O:x/c  O:x/c && |  | ||||||
| 			test_cmp expect actual && |  | ||||||
|  |  | ||||||
| 			git hash-object y/c~HEAD >actual && |  | ||||||
| 			git rev-parse O:x/c >expect && |  | ||||||
| 			test_cmp expect actual |  | ||||||
| 		fi && |  | ||||||
|  |  | ||||||
| 		echo important >expect && | 		echo important >expect && | ||||||
| 		test_cmp expect y/c | 		test_cmp expect y/c | ||||||
|  | @ -3514,8 +3376,6 @@ test_expect_success '10d: Delete untracked with dir rename/rename(2to1)' ' | ||||||
| 		echo important >y/wham && | 		echo important >y/wham && | ||||||
|  |  | ||||||
| 		test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && | 		test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && | ||||||
| 		if test "$GIT_TEST_MERGE_ALGORITHM" = ort |  | ||||||
| 		then |  | ||||||
| 		test_path_is_missing .git/MERGE_HEAD && | 		test_path_is_missing .git/MERGE_HEAD && | ||||||
| 		test_grep "error: The following untracked working tree files would be overwritten by merge" err && | 		test_grep "error: The following untracked working tree files would be overwritten by merge" err && | ||||||
|  |  | ||||||
|  | @ -3524,38 +3384,8 @@ test_expect_success '10d: Delete untracked with dir rename/rename(2to1)' ' | ||||||
| 		git ls-files -u >out && | 		git ls-files -u >out && | ||||||
| 		test_line_count = 0 out && | 		test_line_count = 0 out && | ||||||
| 		git ls-files -o >out && | 		git ls-files -o >out && | ||||||
| 			test_line_count = 3 out |  | ||||||
| 		else |  | ||||||
| 			test_grep "CONFLICT (rename/rename)" out && |  | ||||||
| 			test_grep "Refusing to lose untracked file at y/wham" out && |  | ||||||
|  |  | ||||||
| 			git ls-files -s >out && |  | ||||||
| 			test_line_count = 6 out && |  | ||||||
| 			git ls-files -u >out && |  | ||||||
| 			test_line_count = 2 out && |  | ||||||
| 			git ls-files -o >out && |  | ||||||
| 		test_line_count = 3 out && | 		test_line_count = 3 out && | ||||||
|  |  | ||||||
| 			git rev-parse >actual \ |  | ||||||
| 				:0:y/a :0:y/b :0:y/d :0:y/e :2:y/wham :3:y/wham && |  | ||||||
| 			git rev-parse >expect \ |  | ||||||
| 				 O:z/a  O:z/b  O:x/d  O:x/e  O:z/c     O:x/f && |  | ||||||
| 			test_cmp expect actual && |  | ||||||
|  |  | ||||||
| 			test_must_fail git rev-parse :1:y/wham && |  | ||||||
|  |  | ||||||
| 			# Test that two-way merge in y/wham~merged is as expected |  | ||||||
| 			git cat-file -p :2:y/wham >expect && |  | ||||||
| 			git cat-file -p :3:y/wham >other && |  | ||||||
| 			>empty && |  | ||||||
| 			test_must_fail git merge-file \ |  | ||||||
| 				-L "HEAD" \ |  | ||||||
| 				-L "" \ |  | ||||||
| 				-L "B^0" \ |  | ||||||
| 				expect empty other && |  | ||||||
| 			test_cmp expect y/wham~merged |  | ||||||
| 		fi && |  | ||||||
|  |  | ||||||
| 		echo important >expect && | 		echo important >expect && | ||||||
| 		test_cmp expect y/wham | 		test_cmp expect y/wham | ||||||
| 	) | 	) | ||||||
|  | @ -3596,7 +3426,7 @@ test_setup_10e () { | ||||||
| 	) | 	) | ||||||
| } | } | ||||||
|  |  | ||||||
| test_expect_merge_algorithm failure success '10e: Does git complain about untracked file that is not really in the way?' ' | test_expect_success '10e: Does git complain about untracked file that is not really in the way?' ' | ||||||
| 	test_setup_10e && | 	test_setup_10e && | ||||||
| 	( | 	( | ||||||
| 		cd 10e && | 		cd 10e && | ||||||
|  | @ -3687,30 +3517,8 @@ test_expect_success '11a: Avoid losing dirty contents with simple rename' ' | ||||||
| 		echo stuff >>z/c && | 		echo stuff >>z/c && | ||||||
|  |  | ||||||
| 		test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && | 		test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && | ||||||
| 		if test "$GIT_TEST_MERGE_ALGORITHM" = ort |  | ||||||
| 		then |  | ||||||
| 		test_path_is_missing .git/MERGE_HEAD && | 		test_path_is_missing .git/MERGE_HEAD && | ||||||
| 			test_grep "error: Your local changes to the following files would be overwritten by merge" err | 		test_grep "error: Your local changes to the following files would be overwritten by merge" err && | ||||||
| 		else |  | ||||||
| 			test_grep "Refusing to lose dirty file at z/c" out && |  | ||||||
|  |  | ||||||
| 			git ls-files -s >out && |  | ||||||
| 			test_line_count = 2 out && |  | ||||||
| 			git ls-files -u >out && |  | ||||||
| 			test_line_count = 1 out && |  | ||||||
| 			git ls-files -o >out && |  | ||||||
| 			test_line_count = 3 out && |  | ||||||
|  |  | ||||||
| 			git rev-parse >actual \ |  | ||||||
| 				:0:z/a :2:z/c && |  | ||||||
| 			git rev-parse >expect \ |  | ||||||
| 				 O:z/a  B:z/b && |  | ||||||
| 			test_cmp expect actual && |  | ||||||
|  |  | ||||||
| 			git hash-object z/c~HEAD >actual && |  | ||||||
| 			git rev-parse B:z/b >expect && |  | ||||||
| 			test_cmp expect actual |  | ||||||
| 		fi && |  | ||||||
|  |  | ||||||
| 		test_seq 1 10 >expected && | 		test_seq 1 10 >expected && | ||||||
| 		echo stuff >>expected && | 		echo stuff >>expected && | ||||||
|  | @ -3766,34 +3574,9 @@ test_expect_success '11b: Avoid losing dirty file involved in directory rename' | ||||||
| 		git checkout A^0 && | 		git checkout A^0 && | ||||||
| 		echo stuff >>z/c && | 		echo stuff >>z/c && | ||||||
|  |  | ||||||
| 		if test "$GIT_TEST_MERGE_ALGORITHM" = ort |  | ||||||
| 		then |  | ||||||
| 		test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && | 		test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && | ||||||
| 		test_path_is_missing .git/MERGE_HEAD && | 		test_path_is_missing .git/MERGE_HEAD && | ||||||
| 			test_grep "error: Your local changes to the following files would be overwritten by merge" err | 		test_grep "error: Your local changes to the following files would be overwritten by merge" err && | ||||||
| 		else |  | ||||||
| 			git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && |  | ||||||
| 			test_grep "Refusing to lose dirty file at z/c" out && |  | ||||||
|  |  | ||||||
| 			git ls-files -s >out && |  | ||||||
| 			test_line_count = 3 out && |  | ||||||
| 			git ls-files -u >out && |  | ||||||
| 			test_line_count = 0 out && |  | ||||||
| 			git ls-files -m >out && |  | ||||||
| 			test_line_count = 0 out && |  | ||||||
| 			git ls-files -o >out && |  | ||||||
| 			test_line_count = 3 out && |  | ||||||
|  |  | ||||||
| 			git rev-parse >actual \ |  | ||||||
| 				:0:x/b :0:y/a :0:y/c && |  | ||||||
| 			git rev-parse >expect \ |  | ||||||
| 				 O:x/b  O:z/a  B:x/c && |  | ||||||
| 			test_cmp expect actual && |  | ||||||
|  |  | ||||||
| 			git hash-object y/c >actual && |  | ||||||
| 			git rev-parse B:x/c >expect && |  | ||||||
| 			test_cmp expect actual |  | ||||||
| 		fi && |  | ||||||
|  |  | ||||||
| 		grep -q stuff z/c && | 		grep -q stuff z/c && | ||||||
| 		test_seq 1 10 >expected && | 		test_seq 1 10 >expected && | ||||||
|  | @ -3850,13 +3633,8 @@ test_expect_success '11c: Avoid losing not-uptodate with rename + D/F conflict' | ||||||
| 		echo stuff >>y/c && | 		echo stuff >>y/c && | ||||||
|  |  | ||||||
| 		test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && | 		test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && | ||||||
| 		if test "$GIT_TEST_MERGE_ALGORITHM" = ort |  | ||||||
| 		then |  | ||||||
| 		test_path_is_missing .git/MERGE_HEAD && | 		test_path_is_missing .git/MERGE_HEAD && | ||||||
| 			test_grep "error: Your local changes to the following files would be overwritten by merge" err | 		test_grep "error: Your local changes to the following files would be overwritten by merge" err && | ||||||
| 		else |  | ||||||
| 			test_grep "following files would be overwritten by merge" err |  | ||||||
| 		fi && |  | ||||||
|  |  | ||||||
| 		grep -q stuff y/c && | 		grep -q stuff y/c && | ||||||
| 		test_seq 1 10 >expected && | 		test_seq 1 10 >expected && | ||||||
|  | @ -3924,30 +3702,8 @@ test_expect_success '11d: Avoid losing not-uptodate with rename + D/F conflict' | ||||||
| 		echo stuff >>z/c && | 		echo stuff >>z/c && | ||||||
|  |  | ||||||
| 		test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && | 		test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && | ||||||
| 		if test "$GIT_TEST_MERGE_ALGORITHM" = ort |  | ||||||
| 		then |  | ||||||
| 		test_path_is_missing .git/MERGE_HEAD && | 		test_path_is_missing .git/MERGE_HEAD && | ||||||
| 			test_grep "error: Your local changes to the following files would be overwritten by merge" err | 		test_grep "error: Your local changes to the following files would be overwritten by merge" err && | ||||||
| 		else |  | ||||||
| 			test_grep "Refusing to lose dirty file at z/c" out && |  | ||||||
|  |  | ||||||
| 			git ls-files -s >out && |  | ||||||
| 			test_line_count = 4 out && |  | ||||||
| 			git ls-files -u >out && |  | ||||||
| 			test_line_count = 1 out && |  | ||||||
| 			git ls-files -o >out && |  | ||||||
| 			test_line_count = 4 out && |  | ||||||
|  |  | ||||||
| 			git rev-parse >actual \ |  | ||||||
| 				:0:x/b :0:y/a :0:y/c/d :3:y/c && |  | ||||||
| 			git rev-parse >expect \ |  | ||||||
| 				 O:x/b  O:z/a  B:y/c/d  B:x/c && |  | ||||||
| 			test_cmp expect actual && |  | ||||||
|  |  | ||||||
| 			git hash-object y/c~HEAD >actual && |  | ||||||
| 			git rev-parse B:x/c >expect && |  | ||||||
| 			test_cmp expect actual |  | ||||||
| 		fi && |  | ||||||
|  |  | ||||||
| 		grep -q stuff z/c && | 		grep -q stuff z/c && | ||||||
| 		test_seq 1 10 >expected && | 		test_seq 1 10 >expected && | ||||||
|  | @ -4010,39 +3766,8 @@ test_expect_success '11e: Avoid deleting not-uptodate with dir rename/rename(1to | ||||||
| 		echo mods >>y/c && | 		echo mods >>y/c && | ||||||
|  |  | ||||||
| 		test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && | 		test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && | ||||||
| 		if test "$GIT_TEST_MERGE_ALGORITHM" = ort |  | ||||||
| 		then |  | ||||||
| 		test_path_is_missing .git/MERGE_HEAD && | 		test_path_is_missing .git/MERGE_HEAD && | ||||||
| 			test_grep "error: Your local changes to the following files would be overwritten by merge" err | 		test_grep "error: Your local changes to the following files would be overwritten by merge" err && | ||||||
| 		else |  | ||||||
| 			test_grep "CONFLICT (rename/rename)" out && |  | ||||||
| 			test_grep "Refusing to lose dirty file at y/c" out && |  | ||||||
|  |  | ||||||
| 			git ls-files -s >out && |  | ||||||
| 			test_line_count = 7 out && |  | ||||||
| 			git ls-files -u >out && |  | ||||||
| 			test_line_count = 4 out && |  | ||||||
| 			git ls-files -o >out && |  | ||||||
| 			test_line_count = 3 out && |  | ||||||
|  |  | ||||||
| 			git rev-parse >actual \ |  | ||||||
| 				:0:y/a :0:y/b :0:x/d :1:x/c :2:w/c :2:y/c :3:y/c && |  | ||||||
| 			git rev-parse >expect \ |  | ||||||
| 				 O:z/a  O:z/b  O:x/d  O:x/c  O:x/c  A:y/c  O:x/c && |  | ||||||
| 			test_cmp expect actual && |  | ||||||
|  |  | ||||||
| 			# See if y/c~merged has expected contents; requires manually |  | ||||||
| 			# doing the expected file merge |  | ||||||
| 			git cat-file -p A:y/c >c1 && |  | ||||||
| 			git cat-file -p B:z/c >c2 && |  | ||||||
| 			>empty && |  | ||||||
| 			test_must_fail git merge-file \ |  | ||||||
| 				-L "HEAD" \ |  | ||||||
| 				-L "" \ |  | ||||||
| 				-L "B^0" \ |  | ||||||
| 				c1 empty c2 && |  | ||||||
| 			test_cmp c1 y/c~merged |  | ||||||
| 		fi && |  | ||||||
|  |  | ||||||
| 		echo different >expected && | 		echo different >expected && | ||||||
| 		echo mods >>expected && | 		echo mods >>expected && | ||||||
|  | @ -4099,40 +3824,8 @@ test_expect_success '11f: Avoid deleting not-uptodate with dir rename/rename(2to | ||||||
| 		echo important >>y/wham && | 		echo important >>y/wham && | ||||||
|  |  | ||||||
| 		test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && | 		test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && | ||||||
| 		if test "$GIT_TEST_MERGE_ALGORITHM" = ort |  | ||||||
| 		then |  | ||||||
| 		test_path_is_missing .git/MERGE_HEAD && | 		test_path_is_missing .git/MERGE_HEAD && | ||||||
| 			test_grep "error: Your local changes to the following files would be overwritten by merge" err | 		test_grep "error: Your local changes to the following files would be overwritten by merge" err && | ||||||
| 		else |  | ||||||
| 			test_grep "CONFLICT (rename/rename)" out && |  | ||||||
| 			test_grep "Refusing to lose dirty file at y/wham" out && |  | ||||||
|  |  | ||||||
| 			git ls-files -s >out && |  | ||||||
| 			test_line_count = 4 out && |  | ||||||
| 			git ls-files -u >out && |  | ||||||
| 			test_line_count = 2 out && |  | ||||||
| 			git ls-files -o >out && |  | ||||||
| 			test_line_count = 3 out && |  | ||||||
|  |  | ||||||
| 			test_must_fail git rev-parse :1:y/wham && |  | ||||||
|  |  | ||||||
| 			git rev-parse >actual \ |  | ||||||
| 				:0:y/a :0:y/b :2:y/wham :3:y/wham && |  | ||||||
| 			git rev-parse >expect \ |  | ||||||
| 				 O:z/a  O:z/b  O:x/c     O:x/d && |  | ||||||
| 			test_cmp expect actual && |  | ||||||
|  |  | ||||||
| 			# Test that two-way merge in y/wham~merged is as expected |  | ||||||
| 			git cat-file -p :2:y/wham >expect && |  | ||||||
| 			git cat-file -p :3:y/wham >other && |  | ||||||
| 			>empty && |  | ||||||
| 			test_must_fail git merge-file \ |  | ||||||
| 				-L "HEAD" \ |  | ||||||
| 				-L "" \ |  | ||||||
| 				-L "B^0" \ |  | ||||||
| 				expect empty other && |  | ||||||
| 			test_cmp expect y/wham~merged |  | ||||||
| 		fi && |  | ||||||
|  |  | ||||||
| 		test_seq 1 10 >expected && | 		test_seq 1 10 >expected && | ||||||
| 		echo important >>expected && | 		echo important >>expected && | ||||||
|  | @ -4267,7 +3960,7 @@ test_setup_12b1 () { | ||||||
| 	) | 	) | ||||||
| } | } | ||||||
|  |  | ||||||
| test_expect_merge_algorithm failure success '12b1: Moving two directory hierarchies into each other' ' | test_expect_success '12b1: Moving two directory hierarchies into each other' ' | ||||||
| 	test_setup_12b1 && | 	test_setup_12b1 && | ||||||
| 	( | 	( | ||||||
| 		cd 12b1 && | 		cd 12b1 && | ||||||
|  | @ -4435,7 +4128,7 @@ test_setup_12c1 () { | ||||||
| 	) | 	) | ||||||
| } | } | ||||||
|  |  | ||||||
| test_expect_merge_algorithm failure success '12c1: Moving one directory hierarchy into another w/ content merge' ' | test_expect_success '12c1: Moving one directory hierarchy into another w/ content merge' ' | ||||||
| 	test_setup_12c1 && | 	test_setup_12c1 && | ||||||
| 	( | 	( | ||||||
| 		cd 12c1 && | 		cd 12c1 && | ||||||
|  | @ -4797,7 +4490,7 @@ test_setup_12f () { | ||||||
| 	) | 	) | ||||||
| } | } | ||||||
|  |  | ||||||
| test_expect_merge_algorithm failure success '12f: Trivial directory resolve, caching, all kinds of fun' ' | test_expect_success '12f: Trivial directory resolve, caching, all kinds of fun' ' | ||||||
| 	test_setup_12f && | 	test_setup_12f && | ||||||
| 	( | 	( | ||||||
| 		cd 12f && | 		cd 12f && | ||||||
|  | @ -5253,7 +4946,7 @@ test_setup_12l () { | ||||||
| 	) | 	) | ||||||
| } | } | ||||||
|  |  | ||||||
| test_expect_merge_algorithm failure success '12l (B into A): Rename into each other + add/add conflict' ' | test_expect_success '12l (B into A): Rename into each other + add/add conflict' ' | ||||||
| 	test_setup_12l BintoA && | 	test_setup_12l BintoA && | ||||||
| 	( | 	( | ||||||
| 		cd 12l_BintoA && | 		cd 12l_BintoA && | ||||||
|  | @ -5280,7 +4973,7 @@ test_expect_merge_algorithm failure success '12l (B into A): Rename into each ot | ||||||
| 	) | 	) | ||||||
| ' | ' | ||||||
|  |  | ||||||
| test_expect_merge_algorithm failure success '12l (A into B): Rename into each other + add/add conflict' ' | test_expect_success '12l (A into B): Rename into each other + add/add conflict' ' | ||||||
| 	test_setup_12l AintoB && | 	test_setup_12l AintoB && | ||||||
| 	( | 	( | ||||||
| 		cd 12l_AintoB && | 		cd 12l_AintoB && | ||||||
|  | @ -5348,7 +5041,7 @@ test_setup_12m () { | ||||||
| 	) | 	) | ||||||
| } | } | ||||||
|  |  | ||||||
| test_expect_merge_algorithm failure success '12m: Change parent of renamed-dir to symlink on other side' ' | test_expect_success '12m: Change parent of renamed-dir to symlink on other side' ' | ||||||
| 	test_setup_12m && | 	test_setup_12m && | ||||||
| 	( | 	( | ||||||
| 		cd 12m && | 		cd 12m && | ||||||
|  |  | ||||||
|  | @ -176,9 +176,11 @@ test_expect_success 'merge-recursive, when index==head but head!=HEAD' ' | ||||||
| 	# Make index match B | 	# Make index match B | ||||||
| 	git diff C B -- | git apply --cached && | 	git diff C B -- | git apply --cached && | ||||||
| 	test_when_finished "git clean -fd" &&  # Do not leave untracked around | 	test_when_finished "git clean -fd" &&  # Do not leave untracked around | ||||||
|  | 	git write-tree >index-before && | ||||||
| 	# Merge B & F, with B as "head" | 	# Merge B & F, with B as "head" | ||||||
| 	git merge-recursive A -- B F > out && | 	git merge-recursive A -- B F > out && | ||||||
| 	test_grep "Already up to date" out | 	git write-tree >index-after && | ||||||
|  | 	test_cmp index-before index-after | ||||||
| ' | ' | ||||||
|  |  | ||||||
| test_expect_success 'recursive, when file has staged changes not matching HEAD nor what a merge would give' ' | test_expect_success 'recursive, when file has staged changes not matching HEAD nor what a merge would give' ' | ||||||
|  | @ -294,10 +296,8 @@ test_expect_success 'with multiple strategies, recursive or ort failure do not e | ||||||
| 	git add a && | 	git add a && | ||||||
| 	git rev-parse :a >expect && | 	git rev-parse :a >expect && | ||||||
|  |  | ||||||
| 	sane_unset GIT_TEST_MERGE_ALGORITHM && | 	test_must_fail git merge -s ort -s octopus C^0 >output 2>&1 && | ||||||
| 	test_must_fail git merge -s recursive -s ort -s octopus C^0 >output 2>&1 && |  | ||||||
|  |  | ||||||
| 	grep "Trying merge strategy recursive..." output && |  | ||||||
| 	grep "Trying merge strategy ort..." output && | 	grep "Trying merge strategy ort..." output && | ||||||
| 	grep "Trying merge strategy octopus..." output && | 	grep "Trying merge strategy octopus..." output && | ||||||
| 	grep "No merge strategy handled the merge." output && | 	grep "No merge strategy handled the merge." output && | ||||||
|  |  | ||||||
|  | @ -23,8 +23,6 @@ test_description="merge cases" | ||||||
| #                     files that might be renamed into each other's paths.) | #                     files that might be renamed into each other's paths.) | ||||||
|  |  | ||||||
| . ./test-lib.sh | . ./test-lib.sh | ||||||
| . "$TEST_DIRECTORY"/lib-merge.sh |  | ||||||
|  |  | ||||||
|  |  | ||||||
| ########################################################################### | ########################################################################### | ||||||
| # SECTION 1: Cases involving no renames (one side has subset of changes of | # SECTION 1: Cases involving no renames (one side has subset of changes of | ||||||
|  | @ -663,7 +661,7 @@ test_setup_4a () { | ||||||
| #   correct requires doing the merge in-memory first, then realizing that no | #   correct requires doing the merge in-memory first, then realizing that no | ||||||
| #   updates to the file are necessary, and thus that we can just leave the path | #   updates to the file are necessary, and thus that we can just leave the path | ||||||
| #   alone. | #   alone. | ||||||
| test_expect_merge_algorithm failure success '4a: Change on A, change on B subset of A, dirty mods present' ' | test_expect_success '4a: Change on A, change on B subset of A, dirty mods present' ' | ||||||
| 	test_setup_4a && | 	test_setup_4a && | ||||||
| 	( | 	( | ||||||
| 		cd 4a && | 		cd 4a && | ||||||
|  |  | ||||||
|  | @ -23,8 +23,6 @@ test_description="merge cases" | ||||||
| #                     files that might be renamed into each other's paths.) | #                     files that might be renamed into each other's paths.) | ||||||
|  |  | ||||||
| . ./test-lib.sh | . ./test-lib.sh | ||||||
| . "$TEST_DIRECTORY"/lib-merge.sh |  | ||||||
|  |  | ||||||
|  |  | ||||||
| # Testcase basic, conflicting changes in 'numerals' | # Testcase basic, conflicting changes in 'numerals' | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @ -6,7 +6,6 @@ GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main | ||||||
| export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME | export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME | ||||||
|  |  | ||||||
| . ./test-lib.sh | . ./test-lib.sh | ||||||
| . "$TEST_DIRECTORY"/lib-merge.sh |  | ||||||
|  |  | ||||||
| test_expect_success 'setup 1' ' | test_expect_success 'setup 1' ' | ||||||
|  |  | ||||||
|  | @ -373,9 +372,9 @@ test_expect_success 'merge-recursive d/f conflict result' ' | ||||||
|  |  | ||||||
| 	git ls-files -s >actual && | 	git ls-files -s >actual && | ||||||
| 	( | 	( | ||||||
| 		echo "100644 $o0 1	a" && |  | ||||||
| 		echo "100644 $o1 2	a" && |  | ||||||
| 		echo "100644 $o4 0	a/c" && | 		echo "100644 $o4 0	a/c" && | ||||||
|  | 		echo "100644 $o0 1	a~$c1" && | ||||||
|  | 		echo "100644 $o1 2	a~$c1" && | ||||||
| 		echo "100644 $o0 0	b" && | 		echo "100644 $o0 0	b" && | ||||||
| 		echo "100644 $o0 0	c" && | 		echo "100644 $o0 0	c" && | ||||||
| 		echo "100644 $o1 0	d/e" | 		echo "100644 $o1 0	d/e" | ||||||
|  | @ -397,9 +396,9 @@ test_expect_success 'merge-recursive d/f conflict result the other way' ' | ||||||
|  |  | ||||||
| 	git ls-files -s >actual && | 	git ls-files -s >actual && | ||||||
| 	( | 	( | ||||||
| 		echo "100644 $o0 1	a" && |  | ||||||
| 		echo "100644 $o1 3	a" && |  | ||||||
| 		echo "100644 $o4 0	a/c" && | 		echo "100644 $o4 0	a/c" && | ||||||
|  | 		echo "100644 $o0 1	a~$c1" && | ||||||
|  | 		echo "100644 $o1 3	a~$c1" && | ||||||
| 		echo "100644 $o0 0	b" && | 		echo "100644 $o0 0	b" && | ||||||
| 		echo "100644 $o0 0	c" && | 		echo "100644 $o0 0	c" && | ||||||
| 		echo "100644 $o1 0	d/e" | 		echo "100644 $o1 0	d/e" | ||||||
|  | @ -424,9 +423,9 @@ test_expect_success 'merge-recursive d/f conflict result' ' | ||||||
| 		echo "100644 $o1 0	a" && | 		echo "100644 $o1 0	a" && | ||||||
| 		echo "100644 $o0 0	b" && | 		echo "100644 $o0 0	b" && | ||||||
| 		echo "100644 $o0 0	c" && | 		echo "100644 $o0 0	c" && | ||||||
| 		echo "100644 $o6 3	d" && |  | ||||||
| 		echo "100644 $o0 1	d/e" && | 		echo "100644 $o0 1	d/e" && | ||||||
| 		echo "100644 $o1 2	d/e" | 		echo "100644 $o1 2	d/e" && | ||||||
|  | 		echo "100644 $o6 3	d~$c6" | ||||||
| 	) >expected && | 	) >expected && | ||||||
| 	test_cmp expected actual | 	test_cmp expected actual | ||||||
|  |  | ||||||
|  | @ -448,9 +447,9 @@ test_expect_success 'merge-recursive d/f conflict result' ' | ||||||
| 		echo "100644 $o1 0	a" && | 		echo "100644 $o1 0	a" && | ||||||
| 		echo "100644 $o0 0	b" && | 		echo "100644 $o0 0	b" && | ||||||
| 		echo "100644 $o0 0	c" && | 		echo "100644 $o0 0	c" && | ||||||
| 		echo "100644 $o6 2	d" && |  | ||||||
| 		echo "100644 $o0 1	d/e" && | 		echo "100644 $o0 1	d/e" && | ||||||
| 		echo "100644 $o1 3	d/e" | 		echo "100644 $o1 3	d/e" && | ||||||
|  | 		echo "100644 $o6 2	d~$c6" | ||||||
| 	) >expected && | 	) >expected && | ||||||
| 	test_cmp expected actual | 	test_cmp expected actual | ||||||
|  |  | ||||||
|  | @ -645,7 +644,7 @@ test_expect_success 'merge-recursive copy vs. rename' ' | ||||||
| 	test_cmp expected actual | 	test_cmp expected actual | ||||||
| ' | ' | ||||||
|  |  | ||||||
| test_expect_merge_algorithm failure success 'merge-recursive rename vs. rename/symlink' ' | test_expect_success 'merge-recursive rename vs. rename/symlink' ' | ||||||
|  |  | ||||||
| 	git checkout -f rename && | 	git checkout -f rename && | ||||||
| 	git merge rename-ln && | 	git merge rename-ln && | ||||||
|  | @ -696,33 +695,6 @@ test_expect_success 'merging with triple rename across D/F conflict' ' | ||||||
| 	git merge other | 	git merge other | ||||||
| ' | ' | ||||||
|  |  | ||||||
| test_expect_success 'merge-recursive remembers the names of all base trees' ' |  | ||||||
| 	git reset --hard HEAD && |  | ||||||
|  |  | ||||||
| 	# make the index match $c1 so that merge-recursive below does not |  | ||||||
| 	# fail early |  | ||||||
| 	git diff --binary HEAD $c1 -- | git apply --cached && |  | ||||||
|  |  | ||||||
| 	# more trees than static slots used by oid_to_hex() |  | ||||||
| 	for commit in $c0 $c2 $c4 $c5 $c6 $c7 |  | ||||||
| 	do |  | ||||||
| 		git rev-parse "$commit^{tree}" || return 1 |  | ||||||
| 	done >trees && |  | ||||||
|  |  | ||||||
| 	# ignore the return code; it only fails because the input is weird... |  | ||||||
| 	test_must_fail git -c merge.verbosity=5 merge-recursive $(cat trees) -- $c1 $c3 >out && |  | ||||||
|  |  | ||||||
| 	# ...but make sure it fails in the expected way |  | ||||||
| 	test_grep CONFLICT.*rename/rename out && |  | ||||||
|  |  | ||||||
| 	# merge-recursive prints in reverse order, but we do not care |  | ||||||
| 	sort <trees >expect && |  | ||||||
| 	sed -n "s/^virtual //p" out | sort >actual && |  | ||||||
| 	test_cmp expect actual && |  | ||||||
|  |  | ||||||
| 	git clean -fd |  | ||||||
| ' |  | ||||||
|  |  | ||||||
| test_expect_success 'merge-recursive internal merge resolves to the sameness' ' | test_expect_success 'merge-recursive internal merge resolves to the sameness' ' | ||||||
| 	git reset --hard HEAD && | 	git reset --hard HEAD && | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @ -34,7 +34,9 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME | ||||||
| get_expected_stages () { | get_expected_stages () { | ||||||
| 	git checkout rename -- $1-new && | 	git checkout rename -- $1-new && | ||||||
| 	git ls-files --stage $1-new >expected-stages-undetected-$1 && | 	git ls-files --stage $1-new >expected-stages-undetected-$1 && | ||||||
| 	sed "s/ 0	/ 2	/" <expected-stages-undetected-$1 \ | 	git ls-tree HEAD^ $1-old >tmp && | ||||||
|  | 	git ls-tree HEAD  $1-new >>tmp && | ||||||
|  | 	cat tmp | awk '{print $1 " " $3 " " NR "\t" '$1'"-new"}' \ | ||||||
| 		>expected-stages-detected-$1 && | 		>expected-stages-detected-$1 && | ||||||
| 	git read-tree -u --reset HEAD | 	git read-tree -u --reset HEAD | ||||||
| } | } | ||||||
|  | @ -51,11 +53,11 @@ rename_undetected () { | ||||||
|  |  | ||||||
| check_common () { | check_common () { | ||||||
| 	git ls-files --stage >stages-actual && | 	git ls-files --stage >stages-actual && | ||||||
| 	test_line_count = 4 stages-actual | 	test_line_count = $1 stages-actual | ||||||
| } | } | ||||||
|  |  | ||||||
| check_threshold_0 () { | check_threshold_0 () { | ||||||
| 	check_common && | 	check_common 8 && | ||||||
| 	rename_detected 0 && | 	rename_detected 0 && | ||||||
| 	rename_detected 1 && | 	rename_detected 1 && | ||||||
| 	rename_detected 2 && | 	rename_detected 2 && | ||||||
|  | @ -63,7 +65,7 @@ check_threshold_0 () { | ||||||
| } | } | ||||||
|  |  | ||||||
| check_threshold_1 () { | check_threshold_1 () { | ||||||
| 	check_common && | 	check_common 7 && | ||||||
| 	rename_undetected 0 && | 	rename_undetected 0 && | ||||||
| 	rename_detected 1 && | 	rename_detected 1 && | ||||||
| 	rename_detected 2 && | 	rename_detected 2 && | ||||||
|  | @ -71,7 +73,7 @@ check_threshold_1 () { | ||||||
| } | } | ||||||
|  |  | ||||||
| check_threshold_2 () { | check_threshold_2 () { | ||||||
| 	check_common && | 	check_common 6 && | ||||||
| 	rename_undetected 0 && | 	rename_undetected 0 && | ||||||
| 	rename_undetected 1 && | 	rename_undetected 1 && | ||||||
| 	rename_detected 2 && | 	rename_detected 2 && | ||||||
|  | @ -79,7 +81,7 @@ check_threshold_2 () { | ||||||
| } | } | ||||||
|  |  | ||||||
| check_exact_renames () { | check_exact_renames () { | ||||||
| 	check_common && | 	check_common 5 && | ||||||
| 	rename_undetected 0 && | 	rename_undetected 0 && | ||||||
| 	rename_undetected 1 && | 	rename_undetected 1 && | ||||||
| 	rename_undetected 2 && | 	rename_undetected 2 && | ||||||
|  | @ -87,7 +89,7 @@ check_exact_renames () { | ||||||
| } | } | ||||||
|  |  | ||||||
| check_no_renames () { | check_no_renames () { | ||||||
| 	check_common && | 	check_common 4 && | ||||||
| 	rename_undetected 0 && | 	rename_undetected 0 && | ||||||
| 	rename_undetected 1 && | 	rename_undetected 1 && | ||||||
| 	rename_undetected 2 && | 	rename_undetected 2 && | ||||||
|  |  | ||||||
|  | @ -101,19 +101,10 @@ test_expect_success 'will not overwrite unstaged changes in renamed file' ' | ||||||
| 	git mv c1.c other.c && | 	git mv c1.c other.c && | ||||||
| 	git commit -m rename && | 	git commit -m rename && | ||||||
| 	cp important other.c && | 	cp important other.c && | ||||||
| 	if test "$GIT_TEST_MERGE_ALGORITHM" = ort |  | ||||||
| 	then |  | ||||||
| 	test_must_fail git merge c1a >out 2>err && | 	test_must_fail git merge c1a >out 2>err && | ||||||
| 	test_grep "would be overwritten by merge" err && | 	test_grep "would be overwritten by merge" err && | ||||||
| 	test_cmp important other.c && | 	test_cmp important other.c && | ||||||
| 	test_path_is_missing .git/MERGE_HEAD | 	test_path_is_missing .git/MERGE_HEAD | ||||||
| 	else |  | ||||||
| 		test_must_fail git merge c1a >out && |  | ||||||
| 		test_grep "Refusing to lose dirty file at other.c" out && |  | ||||||
| 		test_path_is_file other.c~HEAD && |  | ||||||
| 		test $(git hash-object other.c~HEAD) = $(git rev-parse c1a:c1.c) && |  | ||||||
| 		test_cmp important other.c |  | ||||||
| 	fi |  | ||||||
| ' | ' | ||||||
|  |  | ||||||
| test_expect_success 'will not overwrite untracked subtree' ' | test_expect_success 'will not overwrite untracked subtree' ' | ||||||
|  |  | ||||||
|  | @ -9,7 +9,6 @@ GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB=1 | ||||||
| export GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB | export GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB | ||||||
|  |  | ||||||
| . ./test-lib.sh | . ./test-lib.sh | ||||||
| . "$TEST_DIRECTORY"/lib-merge.sh |  | ||||||
|  |  | ||||||
| # | # | ||||||
| # history | # history | ||||||
|  | @ -110,14 +109,10 @@ test_expect_success 'merging should conflict for non fast-forward' ' | ||||||
| 	test_when_finished "git -C merge-search reset --hard" && | 	test_when_finished "git -C merge-search reset --hard" && | ||||||
| 	(cd merge-search && | 	(cd merge-search && | ||||||
| 	 git checkout -b test-nonforward-a b && | 	 git checkout -b test-nonforward-a b && | ||||||
| 	  if test "$GIT_TEST_MERGE_ALGORITHM" = ort |  | ||||||
| 	  then |  | ||||||
| 	 test_must_fail git merge c 2>actual && | 	 test_must_fail git merge c 2>actual && | ||||||
| 	 sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short sub-c)" && | 	 sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short sub-c)" && | ||||||
| 	 grep "$sub_expect" actual | 	 grep "$sub_expect" actual | ||||||
| 	  else | 	 ) | ||||||
| 		test_must_fail git merge c 2> actual |  | ||||||
| 	  fi) |  | ||||||
| ' | ' | ||||||
|  |  | ||||||
| test_expect_success 'finish setup for merge-search' ' | test_expect_success 'finish setup for merge-search' ' | ||||||
|  | @ -151,14 +146,9 @@ test_expect_success 'merging should conflict for non fast-forward (resolution ex | ||||||
| 	 git checkout -b test-nonforward-b b && | 	 git checkout -b test-nonforward-b b && | ||||||
| 	 (cd sub && | 	 (cd sub && | ||||||
| 	  git rev-parse --short sub-d > ../expect) && | 	  git rev-parse --short sub-d > ../expect) && | ||||||
| 	  if test "$GIT_TEST_MERGE_ALGORITHM" = ort |  | ||||||
| 	  then |  | ||||||
| 	  test_must_fail git merge c >actual 2>sub-actual && | 	  test_must_fail git merge c >actual 2>sub-actual && | ||||||
| 	  sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short sub-c)" && | 	  sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short sub-c)" && | ||||||
| 		grep "$sub_expect" sub-actual | 	  grep "$sub_expect" sub-actual && | ||||||
| 	  else |  | ||||||
| 		test_must_fail git merge c 2> actual |  | ||||||
| 	  fi && |  | ||||||
| 	 grep $(cat expect) actual > /dev/null && | 	 grep $(cat expect) actual > /dev/null && | ||||||
| 	 git reset --hard) | 	 git reset --hard) | ||||||
| ' | ' | ||||||
|  | @ -169,23 +159,12 @@ test_expect_success 'merging should fail for ambiguous common parent' ' | ||||||
| 	(cd sub && | 	(cd sub && | ||||||
| 	 git checkout -b ambiguous sub-b && | 	 git checkout -b ambiguous sub-b && | ||||||
| 	 git merge sub-c && | 	 git merge sub-c && | ||||||
| 	 if test "$GIT_TEST_MERGE_ALGORITHM" = ort |  | ||||||
| 	 then |  | ||||||
| 	 git rev-parse --short sub-d >../expect1 && | 	 git rev-parse --short sub-d >../expect1 && | ||||||
| 	 git rev-parse --short ambiguous >../expect2 | 	 git rev-parse --short ambiguous >../expect2 | ||||||
| 	 else |  | ||||||
| 		git rev-parse sub-d > ../expect1 && |  | ||||||
| 		git rev-parse ambiguous > ../expect2 |  | ||||||
| 	 fi |  | ||||||
| 	 ) && | 	 ) && | ||||||
| 	 if test "$GIT_TEST_MERGE_ALGORITHM" = ort |  | ||||||
| 	 then |  | ||||||
| 	test_must_fail git merge c >actual 2>sub-actual && | 	test_must_fail git merge c >actual 2>sub-actual && | ||||||
| 	sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short sub-c)" && | 	sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short sub-c)" && | ||||||
| 		grep "$sub_expect" sub-actual | 	grep "$sub_expect" sub-actual && | ||||||
| 	 else |  | ||||||
| 		test_must_fail git merge c 2> actual |  | ||||||
| 	 fi && |  | ||||||
| 	grep $(cat expect1) actual > /dev/null && | 	grep $(cat expect1) actual > /dev/null && | ||||||
| 	grep $(cat expect2) actual > /dev/null && | 	grep $(cat expect2) actual > /dev/null && | ||||||
| 	git reset --hard) | 	git reset --hard) | ||||||
|  | @ -227,11 +206,9 @@ test_expect_success 'merging should fail for changes that are backwards' ' | ||||||
|  |  | ||||||
| 	git checkout -b test-backward e && | 	git checkout -b test-backward e && | ||||||
| 	test_must_fail git merge f 2>actual && | 	test_must_fail git merge f 2>actual && | ||||||
| 	if test "$GIT_TEST_MERGE_ALGORITHM" = ort |  | ||||||
|     then |  | ||||||
| 	sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short sub-d)" && | 	sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short sub-d)" && | ||||||
| 	grep "$sub_expect" actual | 	grep "$sub_expect" actual | ||||||
| 	fi) | 	) | ||||||
| ' | ' | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @ -358,7 +335,7 @@ test_expect_success 'setup file/submodule conflict' ' | ||||||
| 	) | 	) | ||||||
| ' | ' | ||||||
|  |  | ||||||
| test_expect_merge_algorithm failure success 'file/submodule conflict' ' | test_expect_success 'file/submodule conflict' ' | ||||||
| 	test_when_finished "git -C file-submodule reset --hard" && | 	test_when_finished "git -C file-submodule reset --hard" && | ||||||
| 	( | 	( | ||||||
| 		cd file-submodule && | 		cd file-submodule && | ||||||
|  | @ -467,7 +444,7 @@ test_expect_failure 'directory/submodule conflict; keep submodule clean' ' | ||||||
| 	) | 	) | ||||||
| ' | ' | ||||||
|  |  | ||||||
| test_expect_merge_algorithm failure success !FAIL_PREREQS 'directory/submodule conflict; should not treat submodule files as untracked or in the way' ' | test_expect_success !FAIL_PREREQS 'directory/submodule conflict; should not treat submodule files as untracked or in the way' ' | ||||||
| 	test_when_finished "git -C directory-submodule/path reset --hard" && | 	test_when_finished "git -C directory-submodule/path reset --hard" && | ||||||
| 	test_when_finished "git -C directory-submodule reset --hard" && | 	test_when_finished "git -C directory-submodule reset --hard" && | ||||||
| 	( | 	( | ||||||
|  | @ -535,11 +512,9 @@ test_expect_success 'merging should fail with no merge base' ' | ||||||
| 	git add sub && | 	git add sub && | ||||||
| 	git commit -m "b" && | 	git commit -m "b" && | ||||||
| 	test_must_fail git merge a 2>actual && | 	test_must_fail git merge a 2>actual && | ||||||
| 	if test "$GIT_TEST_MERGE_ALGORITHM" = ort |  | ||||||
|     then |  | ||||||
| 	sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short HEAD^1)" && | 	sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short HEAD^1)" && | ||||||
| 	grep "$sub_expect" actual | 	grep "$sub_expect" actual | ||||||
| 	fi) | 	) | ||||||
| ' | ' | ||||||
|  |  | ||||||
| test_done | test_done | ||||||
|  |  | ||||||
|  | @ -12,11 +12,6 @@ test_submodule_switch "merge --ff" | ||||||
|  |  | ||||||
| test_submodule_switch "merge --ff-only" | test_submodule_switch "merge --ff-only" | ||||||
|  |  | ||||||
| if test "$GIT_TEST_MERGE_ALGORITHM" != ort |  | ||||||
| then |  | ||||||
| 	KNOWN_FAILURE_NOFF_MERGE_DOESNT_CREATE_EMPTY_SUBMODULE_DIR=1 |  | ||||||
| 	KNOWN_FAILURE_NOFF_MERGE_ATTEMPTS_TO_MERGE_REMOVED_SUBMODULE_FILES=1 |  | ||||||
| fi |  | ||||||
| test_submodule_switch "merge --no-ff" | test_submodule_switch "merge --no-ff" | ||||||
|  |  | ||||||
| test_done | test_done | ||||||
|  |  | ||||||
|  | @ -47,7 +47,7 @@ test_expect_success 'untracked files overwritten by merge (fast and non-fast for | ||||||
| 		export GIT_MERGE_VERBOSITY && | 		export GIT_MERGE_VERBOSITY && | ||||||
| 		test_must_fail git merge branch 2>out2 | 		test_must_fail git merge branch 2>out2 | ||||||
| 	) && | 	) && | ||||||
| 	echo "Merge with strategy ${GIT_TEST_MERGE_ALGORITHM:-ort} failed." >>expect && | 	echo "Merge with strategy ort failed." >>expect && | ||||||
| 	test_cmp out2 expect && | 	test_cmp out2 expect && | ||||||
| 	git reset --hard HEAD^ | 	git reset --hard HEAD^ | ||||||
| ' | ' | ||||||
|  |  | ||||||
|  | @ -124,11 +124,8 @@ test_expect_success 'rebasing submodule that should conflict' ' | ||||||
| 		echo "160000 $(git rev-parse HEAD) 3	submodule" | 		echo "160000 $(git rev-parse HEAD) 3	submodule" | ||||||
| 	) >expect && | 	) >expect && | ||||||
| 	test_cmp expect actual && | 	test_cmp expect actual && | ||||||
| 	if test "$GIT_TEST_MERGE_ALGORITHM" = ort |  | ||||||
|     then |  | ||||||
| 	sub_expect="go to submodule (submodule), and either merge commit $(git -C submodule rev-parse --short HEAD^0)" && | 	sub_expect="go to submodule (submodule), and either merge commit $(git -C submodule rev-parse --short HEAD^0)" && | ||||||
| 	grep "$sub_expect" actual_output | 	grep "$sub_expect" actual_output | ||||||
| 	fi |  | ||||||
| ' | ' | ||||||
|  |  | ||||||
| test_done | test_done | ||||||
|  |  | ||||||
|  | @ -77,12 +77,9 @@ Merge made by the 'recursive' strategy. | ||||||
| EOF | EOF | ||||||
|  |  | ||||||
| test_expect_success 'merge reduces irrelevant remote heads' ' | test_expect_success 'merge reduces irrelevant remote heads' ' | ||||||
| 	if test "$GIT_TEST_MERGE_ALGORITHM" = ort |  | ||||||
| 	then |  | ||||||
| 	mv expected expected.tmp && | 	mv expected expected.tmp && | ||||||
| 	sed s/recursive/ort/ expected.tmp >expected && | 	sed s/recursive/ort/ expected.tmp >expected && | ||||||
| 		rm expected.tmp | 	rm expected.tmp && | ||||||
| 	fi && |  | ||||||
| 	GIT_MERGE_VERBOSITY=0 git merge c4 c5 >actual && | 	GIT_MERGE_VERBOSITY=0 git merge c4 c5 >actual && | ||||||
| 	test_cmp expected actual | 	test_cmp expected actual | ||||||
| ' | ' | ||||||
|  |  | ||||||
|  | @ -535,14 +535,9 @@ test_expect_success 'file vs modified submodule' ' | ||||||
| 	yes "" | git mergetool file1 file2 spaced\ name subdir/file3 && | 	yes "" | git mergetool file1 file2 spaced\ name subdir/file3 && | ||||||
| 	yes "" | git mergetool both && | 	yes "" | git mergetool both && | ||||||
| 	yes "d" | git mergetool file11 file12 && | 	yes "d" | git mergetool file11 file12 && | ||||||
| 	if test "$GIT_TEST_MERGE_ALGORITHM" = ort |  | ||||||
| 	then |  | ||||||
| 	yes "c" | git mergetool submod~HEAD && | 	yes "c" | git mergetool submod~HEAD && | ||||||
| 	git rm submod && | 	git rm submod && | ||||||
| 		git mv submod~HEAD submod | 	git mv submod~HEAD submod && | ||||||
| 	else |  | ||||||
| 		yes "l" | git mergetool submod |  | ||||||
| 	fi && |  | ||||||
| 	git submodule update -N && | 	git submodule update -N && | ||||||
| 	echo "not a submodule" >expect && | 	echo "not a submodule" >expect && | ||||||
| 	test_cmp expect submod && | 	test_cmp expect submod && | ||||||
|  | @ -559,15 +554,10 @@ test_expect_success 'file vs modified submodule' ' | ||||||
| 	yes "" | git mergetool file1 file2 spaced\ name subdir/file3 && | 	yes "" | git mergetool file1 file2 spaced\ name subdir/file3 && | ||||||
| 	yes "" | git mergetool both && | 	yes "" | git mergetool both && | ||||||
| 	yes "d" | git mergetool file11 file12 && | 	yes "d" | git mergetool file11 file12 && | ||||||
| 	if test "$GIT_TEST_MERGE_ALGORITHM" = ort |  | ||||||
| 	then |  | ||||||
| 	mv submod submod.orig && | 	mv submod submod.orig && | ||||||
| 	git rm --cached submod && | 	git rm --cached submod && | ||||||
| 	yes "c" | git mergetool submod~test19 && | 	yes "c" | git mergetool submod~test19 && | ||||||
| 		git mv submod~test19 submod | 	git mv submod~test19 submod && | ||||||
| 	else |  | ||||||
| 		yes "r" | git mergetool submod |  | ||||||
| 	fi && |  | ||||||
| 	test -d submod.orig && | 	test -d submod.orig && | ||||||
| 	git submodule update -N && | 	git submodule update -N && | ||||||
| 	echo "not a submodule" >expect && | 	echo "not a submodule" >expect && | ||||||
|  | @ -585,10 +575,7 @@ test_expect_success 'file vs modified submodule' ' | ||||||
| 	yes "" | git mergetool both && | 	yes "" | git mergetool both && | ||||||
| 	yes "d" | git mergetool file11 file12 && | 	yes "d" | git mergetool file11 file12 && | ||||||
| 	yes "l" | git mergetool submod && | 	yes "l" | git mergetool submod && | ||||||
| 	if test "$GIT_TEST_MERGE_ALGORITHM" = ort | 	yes "d" | git mergetool submod~test19 && | ||||||
| 	then |  | ||||||
| 		yes "d" | git mergetool submod~test19 |  | ||||||
| 	fi && |  | ||||||
| 	echo "main submodule" >expect && | 	echo "main submodule" >expect && | ||||||
| 	test_cmp expect submod/bar && | 	test_cmp expect submod/bar && | ||||||
| 	git submodule update -N && | 	git submodule update -N && | ||||||
|  | @ -686,14 +673,9 @@ test_expect_success 'directory vs modified submodule' ' | ||||||
| 	test_must_fail git merge main && | 	test_must_fail git merge main && | ||||||
| 	test -n "$(git ls-files -u)" && | 	test -n "$(git ls-files -u)" && | ||||||
| 	test ! -e submod.orig && | 	test ! -e submod.orig && | ||||||
| 	if test "$GIT_TEST_MERGE_ALGORITHM" = ort |  | ||||||
| 	then |  | ||||||
| 	yes "r" | git mergetool submod~main && | 	yes "r" | git mergetool submod~main && | ||||||
| 	git mv submod submod.orig && | 	git mv submod submod.orig && | ||||||
| 		git mv submod~main submod | 	git mv submod~main submod && | ||||||
| 	else |  | ||||||
| 		yes "r" | git mergetool submod |  | ||||||
| 	fi && |  | ||||||
| 	test -d submod.orig && | 	test -d submod.orig && | ||||||
| 	echo "not a submodule" >expect && | 	echo "not a submodule" >expect && | ||||||
| 	test_cmp expect submod.orig/file16 && | 	test_cmp expect submod.orig/file16 && | ||||||
|  |  | ||||||
|  | @ -22,8 +22,6 @@ test_expect_success 'setup' ' | ||||||
| 	git tag c2 | 	git tag c2 | ||||||
| ' | ' | ||||||
|  |  | ||||||
| GIT_TEST_MERGE_ALGORITHM=recursive |  | ||||||
|  |  | ||||||
| test_expect_success 'merge c2 to c1 with recursive merge strategy fails with the current default myers diff algorithm' ' | test_expect_success 'merge c2 to c1 with recursive merge strategy fails with the current default myers diff algorithm' ' | ||||||
| 	git reset --hard c1 && | 	git reset --hard c1 && | ||||||
| 	test_must_fail git merge -s recursive -Xdiff-algorithm=myers c2 | 	test_must_fail git merge -s recursive -Xdiff-algorithm=myers c2 | ||||||
|  |  | ||||||
|  | @ -540,8 +540,6 @@ GIT_DEFAULT_HASH="${GIT_TEST_DEFAULT_HASH:-sha1}" | ||||||
| export GIT_DEFAULT_HASH | export GIT_DEFAULT_HASH | ||||||
| GIT_DEFAULT_REF_FORMAT="${GIT_TEST_DEFAULT_REF_FORMAT:-files}" | GIT_DEFAULT_REF_FORMAT="${GIT_TEST_DEFAULT_REF_FORMAT:-files}" | ||||||
| export GIT_DEFAULT_REF_FORMAT | export GIT_DEFAULT_REF_FORMAT | ||||||
| GIT_TEST_MERGE_ALGORITHM="${GIT_TEST_MERGE_ALGORITHM:-ort}" |  | ||||||
| export GIT_TEST_MERGE_ALGORITHM |  | ||||||
|  |  | ||||||
| # Tests using GIT_TRACE typically don't want <timestamp> <file>:<line> output | # Tests using GIT_TRACE typically don't want <timestamp> <file>:<line> output | ||||||
| GIT_TRACE_BARE=1 | GIT_TRACE_BARE=1 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue