Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.kernel.org/pub/scm/git/git.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2018-09-05 00:31:38 +0300
committerJunio C Hamano <gitster@pobox.com>2018-09-05 00:31:38 +0300
commitca676b9bd354e846ac207e7879760719826517ce (patch)
treede33f48393a62396f73111655a41ae77f6be63c9
parent064e0b2d4ca76b0c438545a4d2170e589327e31f (diff)
parent6aba117d5cf7128e7bc942888263552fe927e13f (diff)
Merge branch 'en/directory-renames-nothanks'
Recent addition of "directory rename" heuristics to the merge-recursive backend makes the command susceptible to false positives and false negatives. In the context of "git am -3", which does not know about surrounding unmodified paths and thus cannot inform the merge machinery about the full trees involved, this risk is particularly severe. As such, the heuristic is disabled for "git am -3" to keep the machinery "more stupid but predictable". * en/directory-renames-nothanks: am: avoid directory rename detection when calling recursive merge machinery merge-recursive: add ability to turn off directory rename detection t3401: add another directory rename testcase for rebase and am
-rw-r--r--builtin/am.c1
-rw-r--r--merge-recursive.c18
-rw-r--r--merge-recursive.h1
-rwxr-xr-xt/t3401-rebase-and-am-rename.sh110
4 files changed, 124 insertions, 6 deletions
diff --git a/builtin/am.c b/builtin/am.c
index 9f7ecf6ecb..5e866d17c7 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -1598,6 +1598,7 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa
o.branch1 = "HEAD";
their_tree_name = xstrfmt("%.*s", linelen(state->msg), state->msg);
o.branch2 = their_tree_name;
+ o.detect_directory_renames = 0;
if (state->quiet)
o.verbosity = 0;
diff --git a/merge-recursive.c b/merge-recursive.c
index dcdc93019c..e5243dbc54 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -2869,12 +2869,19 @@ static int detect_and_process_renames(struct merge_options *o,
head_pairs = get_diffpairs(o, common, head);
merge_pairs = get_diffpairs(o, common, merge);
- dir_re_head = get_directory_renames(head_pairs, head);
- dir_re_merge = get_directory_renames(merge_pairs, merge);
+ if (o->detect_directory_renames) {
+ dir_re_head = get_directory_renames(head_pairs, head);
+ dir_re_merge = get_directory_renames(merge_pairs, merge);
- handle_directory_level_conflicts(o,
- dir_re_head, head,
- dir_re_merge, merge);
+ handle_directory_level_conflicts(o,
+ dir_re_head, head,
+ dir_re_merge, merge);
+ } else {
+ dir_re_head = xmalloc(sizeof(*dir_re_head));
+ dir_re_merge = xmalloc(sizeof(*dir_re_merge));
+ dir_rename_init(dir_re_head);
+ dir_rename_init(dir_re_merge);
+ }
ri->head_renames = get_renames(o, head_pairs,
dir_re_merge, dir_re_head, head,
@@ -3586,6 +3593,7 @@ void init_merge_options(struct merge_options *o)
o->renormalize = 0;
o->diff_detect_rename = -1;
o->merge_detect_rename = -1;
+ o->detect_directory_renames = 1;
merge_recursive_config(o);
merge_verbosity = getenv("GIT_MERGE_VERBOSITY");
if (merge_verbosity)
diff --git a/merge-recursive.h b/merge-recursive.h
index 0c46a5a4ff..e6a0828eca 100644
--- a/merge-recursive.h
+++ b/merge-recursive.h
@@ -20,6 +20,7 @@ struct merge_options {
unsigned renormalize : 1;
long xdl_opts;
int verbosity;
+ int detect_directory_renames;
int diff_detect_rename;
int merge_detect_rename;
int diff_rename_limit;
diff --git a/t/t3401-rebase-and-am-rename.sh b/t/t3401-rebase-and-am-rename.sh
index 8f832957fc..e0b5111993 100755
--- a/t/t3401-rebase-and-am-rename.sh
+++ b/t/t3401-rebase-and-am-rename.sh
@@ -5,7 +5,7 @@ test_description='git rebase + directory rename tests'
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-rebase.sh
-test_expect_success 'setup testcase' '
+test_expect_success 'setup testcase where directory rename should be detected' '
test_create_repo dir-rename &&
(
cd dir-rename &&
@@ -102,4 +102,112 @@ test_expect_failure 'am: directory rename detected' '
)
'
+test_expect_success 'setup testcase where directory rename should NOT be detected' '
+ test_create_repo no-dir-rename &&
+ (
+ cd no-dir-rename &&
+
+ mkdir x &&
+ test_seq 1 10 >x/a &&
+ test_seq 11 20 >x/b &&
+ test_seq 21 30 >x/c &&
+ echo original >project_info &&
+ git add x project_info &&
+ git commit -m "Initial" &&
+
+ git branch O &&
+ git branch A &&
+ git branch B &&
+
+ git checkout A &&
+ echo v2 >project_info &&
+ git add project_info &&
+ git commit -m "Modify project_info" &&
+
+ git checkout B &&
+ mkdir y &&
+ git mv x/c y/c &&
+ echo v1 >project_info &&
+ git add project_info &&
+ git commit -m "Rename x/c to y/c, modify project_info"
+ )
+'
+
+test_expect_success 'rebase --interactive: NO directory rename' '
+ test_when_finished "git -C no-dir-rename rebase --abort" &&
+ (
+ cd no-dir-rename &&
+
+ git checkout B^0 &&
+
+ set_fake_editor &&
+ test_must_fail env FAKE_LINES="1" git rebase --interactive A &&
+
+ git ls-files -s >out &&
+ test_line_count = 6 out &&
+
+ test_path_is_file x/a &&
+ test_path_is_file x/b &&
+ test_path_is_missing x/c
+ )
+'
+
+test_expect_success 'rebase (am): NO directory rename' '
+ test_when_finished "git -C no-dir-rename rebase --abort" &&
+ (
+ cd no-dir-rename &&
+
+ git checkout B^0 &&
+
+ set_fake_editor &&
+ test_must_fail git rebase A &&
+
+ git ls-files -s >out &&
+ test_line_count = 6 out &&
+
+ test_path_is_file x/a &&
+ test_path_is_file x/b &&
+ test_path_is_missing x/c
+ )
+'
+
+test_expect_success 'rebase --merge: NO directory rename' '
+ test_when_finished "git -C no-dir-rename rebase --abort" &&
+ (
+ cd no-dir-rename &&
+
+ git checkout B^0 &&
+
+ set_fake_editor &&
+ test_must_fail git rebase --merge A &&
+
+ git ls-files -s >out &&
+ test_line_count = 6 out &&
+
+ test_path_is_file x/a &&
+ test_path_is_file x/b &&
+ test_path_is_missing x/c
+ )
+'
+
+test_expect_success 'am: NO directory rename' '
+ test_when_finished "git -C no-dir-rename am --abort" &&
+ (
+ cd no-dir-rename &&
+
+ git checkout A^0 &&
+
+ git format-patch -1 B &&
+
+ test_must_fail git am --3way 0001*.patch &&
+
+ git ls-files -s >out &&
+ test_line_count = 6 out &&
+
+ test_path_is_file x/a &&
+ test_path_is_file x/b &&
+ test_path_is_missing x/c
+ )
+'
+
test_done