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()
main
Junio C Hamano 2025-04-17 10:28:18 -07:00
commit c3ebf18eb2
46 changed files with 526 additions and 5229 deletions

View File

@ -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

View File

@ -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.



View File

@ -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

View File

@ -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,10 +907,10 @@ 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);
if (ret < 0) if (ret < 0)
exit(128); exit(128);
ret = reset_tree(new_tree, ret = reset_tree(new_tree,

View File

@ -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);

View File

@ -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 */

View File

@ -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();

View File

@ -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') {

View File

@ -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

View File

@ -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.

View File

@ -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;
}

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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',

View File

@ -781,28 +781,19 @@ 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, &result);
merge_incore_nonrecursive(&o, base_tree, head_tree, next_tree, show_output = !is_rebase_i(opts) || !result.clean;
&result); /*
show_output = !is_rebase_i(opts) || !result.clean; * TODO: merge_switch_to_result will update index/working tree;
/* * we only really want to do that if !result.clean || this is
* TODO: merge_switch_to_result will update index/working tree; * the final patch to be picked. But determining this is the
* we only really want to do that if !result.clean || this is * final patch would take some work, and "head_tree" would need
* the final patch to be picked. But determining this is the * to be replace with the tree the index matched before we
* final patch would take some work, and "head_tree" would need * started doing any picks.
* to be replace with the tree the index matched before we */
* started doing any picks. merge_switch_to_result(&o, head_tree, &result, 1, show_output);
*/ clean = result.clean;
merge_switch_to_result(&o, head_tree, &result, 1, show_output);
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, head_commit, merge_commit, bases, &i);
ret = merge_ort_recursive(&o,
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

View File

@ -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
}

View File

@ -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
) )

View File

@ -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
' '

View File

@ -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' '

View File

@ -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

View File

@ -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 &&

View File

@ -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 &&

View File

@ -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' '

View File

@ -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 &&

View File

@ -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,63 +498,33 @@ 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 git checkout -q rename-one^0 &&
test_expect_success 'pair rename to parent of other (D/F conflicts) w/ untracked dir' ' mkdir one &&
git checkout -q rename-one^0 && test_must_fail git merge --strategy=recursive rename-two &&
mkdir one &&
test_must_fail git merge --strategy=recursive rename-two &&


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 &&


test_must_fail git diff --quiet && test_must_fail git diff --quiet &&


test 3 -eq $(find . | grep -v .git | wc -l) && test 3 -eq $(find . | grep -v .git | wc -l) &&


test_path_is_file one && test_path_is_file one &&
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 test_stdout_line_count = 4 git ls-files -u &&
then test_stdout_line_count = 2 git ls-files -u one &&
test_stdout_line_count = 4 git ls-files -u && test_stdout_line_count = 2 git ls-files -u two &&
test_stdout_line_count = 2 git ls-files -u one &&
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 test_stdout_line_count = 5 git ls-files -s &&
then test_stdout_line_count = 3 git ls-files -u &&
test_stdout_line_count = 5 git ls-files -s && test_stdout_line_count = 1 git ls-files -u one~HEAD &&
test_stdout_line_count = 3 git ls-files -u && test_stdout_line_count = 1 git ls-files -u two~second-rename &&
test_stdout_line_count = 1 git ls-files -u one~HEAD && test_stdout_line_count = 1 git ls-files -u original &&
test_stdout_line_count = 1 git ls-files -u two~second-rename && test_stdout_line_count = 0 git ls-files -o &&
test_stdout_line_count = 1 git ls-files -u original &&
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 &&

View 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
' '

View File

@ -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
' '



View File

@ -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 git rm -rf a/ &&
then git rm a~HEAD &&
git rm -rf a/ &&
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 git rm -rf a/ &&
then git rm a~B^0 &&
git rm -rf a/ &&
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,34 +576,16 @@ 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 git ls-files -s >out &&
then test_line_count = 3 out &&
git ls-files -s >out && git ls-files -u >out &&
test_line_count = 3 out && test_line_count = 2 out &&
git ls-files -u >out && git ls-files -o >out &&
test_line_count = 2 out && test_line_count = 1 out &&
git ls-files -o >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 \ test_cmp expect actual
:0:ignore-me :1:a :2:a &&
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,34 +599,18 @@ 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 git ls-files -s >out &&
then test_line_count = 3 out &&
git ls-files -s >out && git ls-files -u >out &&
test_line_count = 3 out && test_line_count = 2 out &&
git ls-files -u >out && git ls-files -o >out &&
test_line_count = 2 out && test_line_count = 1 out &&
git ls-files -o >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 \ 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,32 +624,17 @@ 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 git ls-files -s >out &&
then test_line_count = 5 out &&
git ls-files -s >out && git ls-files -u >out &&
test_line_count = 5 out && test_line_count = 4 out &&
git ls-files -u >out && git ls-files -o >out &&
test_line_count = 4 out && test_line_count = 1 out &&
git ls-files -o >out &&
test_line_count = 1 out &&


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,32 +651,17 @@ 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 git ls-files -s >out &&
then test_line_count = 5 out &&
git ls-files -s >out && git ls-files -u >out &&
test_line_count = 5 out && test_line_count = 4 out &&
git ls-files -u >out && git ls-files -o >out &&
test_line_count = 4 out && test_line_count = 1 out &&
git ls-files -o >out &&
test_line_count = 1 out &&


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 &&



View File

@ -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 &&
( (

View File

@ -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 git rev-parse >actual \
then :1:newfile~HEAD :2:newfile~HEAD :3:newfile~HEAD &&
git rev-parse >actual \
: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 &&

View File

@ -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 test_must_fail git merge-file \
then -L "HEAD:y/wham" \
test_must_fail git merge-file \ -L "" \
-L "HEAD:y/wham" \ -L "B^0:z/wham" \
-L "" \ expect empty other &&
-L "B^0:z/wham" \
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 test_line_count = 1 out &&
then
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,32 +1261,17 @@ 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 git ls-files -s >out &&
then test_line_count = 3 out &&
git ls-files -s >out && git ls-files -u >out &&
test_line_count = 3 out && test_line_count = 2 out &&
git ls-files -u >out && git ls-files -o >out &&
test_line_count = 2 out && test_line_count = 1 out &&
git ls-files -o >out &&
test_line_count = 1 out &&


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 test_must_fail git merge-file \
then -L "HEAD:y/d" \
test_must_fail git merge-file \ -L "" \
-L "HEAD:y/d" \ -L "B^0:z/d" \
-L "" \ expect empty other &&
-L "B^0:z/d" \
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,32 +1924,17 @@ 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 git ls-files -s >out &&
then test_line_count = 4 out &&
git ls-files -s >out && git ls-files -u >out &&
test_line_count = 4 out && test_line_count = 2 out &&
git ls-files -u >out && git ls-files -o >out &&
test_line_count = 2 out && test_line_count = 1 out &&
git ls-files -o >out &&
test_line_count = 1 out &&


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,32 +2015,17 @@ 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 git ls-files -s >out &&
then test_line_count = 6 out &&
git ls-files -s >out && git ls-files -u >out &&
test_line_count = 6 out && test_line_count = 2 out &&
git ls-files -u >out && git ls-files -o >out &&
test_line_count = 2 out && test_line_count = 1 out &&
git ls-files -o >out &&
test_line_count = 1 out &&


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,34 +3211,15 @@ 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 test_path_is_missing .git/MERGE_HEAD &&
then test_grep "error: The following untracked working tree files would be overwritten by merge" err &&
test_path_is_missing .git/MERGE_HEAD &&
test_grep "error: The following untracked working tree files would be overwritten by merge" err &&


git ls-files -s >out && git ls-files -s >out &&
test_line_count = 1 out && test_line_count = 1 out &&
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 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 &&

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,38 +3282,15 @@ 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 test_path_is_missing .git/MERGE_HEAD &&
then test_grep "error: The following untracked working tree files would be overwritten by merge" err &&
test_path_is_missing .git/MERGE_HEAD &&
test_grep "error: The following untracked working tree files would be overwritten by merge" err &&


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 &&
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 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 &&
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,38 +3310,15 @@ 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 test_path_is_missing .git/MERGE_HEAD &&
then test_grep "error: The following untracked working tree files would be overwritten by merge" err &&
test_path_is_missing .git/MERGE_HEAD &&
test_grep "error: The following untracked working tree files would be overwritten by merge" err &&


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 &&
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 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 &&
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,47 +3376,15 @@ 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 test_path_is_missing .git/MERGE_HEAD &&
then test_grep "error: The following untracked working tree files would be overwritten by merge" err &&
test_path_is_missing .git/MERGE_HEAD &&
test_grep "error: The following untracked working tree files would be overwritten by merge" err &&


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 &&
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 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 &&

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 test_path_is_missing .git/MERGE_HEAD &&
then test_grep "error: Your local changes to the following files would be overwritten by merge" err &&
test_path_is_missing .git/MERGE_HEAD &&
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 test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err &&
then test_path_is_missing .git/MERGE_HEAD &&
test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && test_grep "error: Your local changes to the following files would be overwritten by merge" err &&
test_path_is_missing .git/MERGE_HEAD &&
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 test_path_is_missing .git/MERGE_HEAD &&
then test_grep "error: Your local changes to the following files would be overwritten by merge" err &&
test_path_is_missing .git/MERGE_HEAD &&
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 test_path_is_missing .git/MERGE_HEAD &&
then test_grep "error: Your local changes to the following files would be overwritten by merge" err &&
test_path_is_missing .git/MERGE_HEAD &&
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 test_path_is_missing .git/MERGE_HEAD &&
then test_grep "error: Your local changes to the following files would be overwritten by merge" err &&
test_path_is_missing .git/MERGE_HEAD &&
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 test_path_is_missing .git/MERGE_HEAD &&
then test_grep "error: Your local changes to the following files would be overwritten by merge" err &&
test_path_is_missing .git/MERGE_HEAD &&
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 &&

View File

@ -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 &&

View File

@ -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 &&

View File

@ -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'



View File

@ -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 &&



View File

@ -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 &&

View File

@ -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 test_must_fail git merge c1a >out 2>err &&
then test_grep "would be overwritten by merge" err &&
test_must_fail git merge c1a >out 2>err && test_cmp important other.c &&
test_grep "would be overwritten by merge" err && test_path_is_missing .git/MERGE_HEAD
test_cmp important other.c &&
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' '

View File

@ -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 test_must_fail git merge c 2>actual &&
then sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short sub-c)" &&
test_must_fail git merge c 2>actual && grep "$sub_expect" actual
sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short sub-c)" && )
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 test_must_fail git merge c >actual 2>sub-actual &&
then sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short sub-c)" &&
test_must_fail git merge c >actual 2>sub-actual && grep "$sub_expect" sub-actual &&
sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short sub-c)" &&
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 git rev-parse --short sub-d >../expect1 &&
then git rev-parse --short ambiguous >../expect2
git rev-parse --short sub-d >../expect1 &&
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 test_must_fail git merge c >actual 2>sub-actual &&
then sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short sub-c)" &&
test_must_fail git merge c >actual 2>sub-actual && grep "$sub_expect" sub-actual &&
sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short sub-c)" &&
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 sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short sub-d)" &&
then grep "$sub_expect" actual
sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short sub-d)" && )
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 sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short HEAD^1)" &&
then grep "$sub_expect" actual
sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short HEAD^1)" && )
grep "$sub_expect" actual
fi)
' '


test_done test_done

View File

@ -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

View File

@ -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^
' '

View File

@ -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 sub_expect="go to submodule (submodule), and either merge commit $(git -C submodule rev-parse --short HEAD^0)" &&
then grep "$sub_expect" actual_output
sub_expect="go to submodule (submodule), and either merge commit $(git -C submodule rev-parse --short HEAD^0)" &&
grep "$sub_expect" actual_output
fi
' '


test_done test_done

View File

@ -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 mv expected expected.tmp &&
then sed s/recursive/ort/ expected.tmp >expected &&
mv expected expected.tmp && rm expected.tmp &&
sed s/recursive/ort/ expected.tmp >expected &&
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
' '

View File

@ -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 yes "c" | git mergetool submod~HEAD &&
then git rm submod &&
yes "c" | git mergetool submod~HEAD && git mv submod~HEAD submod &&
git rm 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 mv submod submod.orig &&
then git rm --cached submod &&
mv submod submod.orig && yes "c" | git mergetool submod~test19 &&
git rm --cached submod && git mv submod~test19 submod &&
yes "c" | git mergetool submod~test19 &&
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 yes "r" | git mergetool submod~main &&
then git mv submod submod.orig &&
yes "r" | git mergetool submod~main && git mv submod~main submod &&
git mv submod submod.orig &&
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 &&

View File

@ -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

View File

@ -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