From: Junio C Hamano Date: Wed, 24 Nov 2010 23:55:36 +0000 (-0800) Subject: Merge branch 'cb/maint-orphan-merge-noclobber' X-Git-Tag: v1.7.4-rc0~117 X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=7d43de925b2771d295d8fc4341b7bd544e2a74fa;hp=-c;p=git.git Merge branch 'cb/maint-orphan-merge-noclobber' * cb/maint-orphan-merge-noclobber: do not overwrite untracked during merge from unborn branch --- 7d43de925b2771d295d8fc4341b7bd544e2a74fa diff --combined builtin/merge.c index 9ec13f14b,2a6c49f6c..c24a7be02 --- a/builtin/merge.c +++ b/builtin/merge.c @@@ -42,7 -42,7 +42,7 @@@ static const char * const builtin_merge NULL }; -static int show_diffstat = 1, option_log, squash; +static int show_diffstat = 1, shortlog_len, squash; static int option_commit = 1, allow_fast_forward = 1; static int fast_forward_only; static int allow_trivial = 1, have_message; @@@ -54,7 -54,6 +54,7 @@@ static size_t use_strategies_nr, use_st static const char **xopts; static size_t xopts_nr, xopts_alloc; static const char *branch; +static int option_renormalize; static int verbosity; static int allow_rerere_auto; @@@ -132,7 -131,6 +132,7 @@@ static struct strategy *get_strategy(co ret = xcalloc(1, sizeof(struct strategy)); ret->name = xstrdup(name); + ret->attr = NO_TRIVIAL; return ret; } @@@ -177,9 -175,8 +177,9 @@@ static struct option builtin_merge_opti OPT_BOOLEAN(0, "stat", &show_diffstat, "show a diffstat at the end of the merge"), OPT_BOOLEAN(0, "summary", &show_diffstat, "(synonym to --stat)"), - OPT_BOOLEAN(0, "log", &option_log, - "add list of one-line log to merge commit message"), + { OPTION_INTEGER, 0, "log", &shortlog_len, "n", + "add (at most ) entries from shortlog to merge commit message", + PARSE_OPT_OPTARG, NULL, DEFAULT_MERGE_LOG_LEN }, OPT_BOOLEAN(0, "squash", &squash, "create a single commit instead of doing a merge"), OPT_BOOLEAN(0, "commit", &option_commit, @@@ -234,6 -231,24 +234,24 @@@ static void save_state(void die("not a valid object: %s", buffer.buf); } + static void read_empty(unsigned const char *sha1, int verbose) + { + int i = 0; + const char *args[7]; + + args[i++] = "read-tree"; + if (verbose) + args[i++] = "-v"; + args[i++] = "-m"; + args[i++] = "-u"; + args[i++] = EMPTY_TREE_SHA1_HEX; + args[i++] = sha1_to_hex(sha1); + args[i] = NULL; + + if (run_command_v_opt(args, RUN_GIT_CMD)) + die("read-tree failed"); + } + static void reset_hard(unsigned const char *sha1, int verbose) { int i = 0; @@@ -403,7 -418,7 +421,7 @@@ static void merge_name(const char *remo goto cleanup; } if (!prefixcmp(found_ref, "refs/remotes/")) { - strbuf_addf(msg, "%s\t\tremote branch '%s' of .\n", + strbuf_addf(msg, "%s\t\tremote-tracking branch '%s' of .\n", sha1_to_hex(branch_head), remote); goto cleanup; } @@@ -440,7 -455,7 +458,7 @@@ strbuf_addstr(&truname, "refs/heads/"); strbuf_addstr(&truname, remote); strbuf_setlen(&truname, truname.len - len); - if (resolve_ref(truname.buf, buf_sha, 0, NULL)) { + if (resolve_ref(truname.buf, buf_sha, 1, NULL)) { strbuf_addf(msg, "%s\t\tbranch '%s'%s of .\n", sha1_to_hex(remote_head->sha1), @@@ -489,8 -504,7 +507,8 @@@ static int git_merge_config(const char buf = xstrdup(v); argc = split_cmdline(buf, &argv); if (argc < 0) - die("Bad branch.%s.mergeoptions string", branch); + die("Bad branch.%s.mergeoptions string: %s", branch, + split_cmdline_strerror(argc)); argv = xrealloc(argv, sizeof(*argv) * (argc + 2)); memmove(argv + 1, argv, sizeof(*argv) * (argc + 1)); argc++; @@@ -505,17 -519,8 +523,17 @@@ return git_config_string(&pull_twohead, k, v); else if (!strcmp(k, "pull.octopus")) return git_config_string(&pull_octopus, k, v); - else if (!strcmp(k, "merge.log") || !strcmp(k, "merge.summary")) - option_log = git_config_bool(k, v); + else if (!strcmp(k, "merge.renormalize")) + option_renormalize = git_config_bool(k, v); + else if (!strcmp(k, "merge.log") || !strcmp(k, "merge.summary")) { + int is_bool; + shortlog_len = git_config_bool_or_int(k, v, &is_bool); + if (!is_bool && shortlog_len < 0) + return error("%s: negative length %s", k, v); + if (is_bool && shortlog_len) + shortlog_len = DEFAULT_MERGE_LOG_LEN; + return 0; + } return git_diff_ui_config(k, v, cb); } @@@ -637,11 -642,18 +655,11 @@@ static int try_merge_strategy(const cha if (!strcmp(strategy, "subtree")) o.subtree_shift = ""; - for (x = 0; x < xopts_nr; x++) { - if (!strcmp(xopts[x], "ours")) - o.recursive_variant = MERGE_RECURSIVE_OURS; - else if (!strcmp(xopts[x], "theirs")) - o.recursive_variant = MERGE_RECURSIVE_THEIRS; - else if (!strcmp(xopts[x], "subtree")) - o.subtree_shift = ""; - else if (!prefixcmp(xopts[x], "subtree=")) - o.subtree_shift = xopts[x]+8; - else + o.renormalize = option_renormalize; + + for (x = 0; x < xopts_nr; x++) + if (parse_merge_opt(&o, xopts[x])) die("Unknown option for merge-recursive: -X%s", xopts[x]); - } o.branch1 = head_arg; o.branch2 = remoteheads->item->util; @@@ -710,7 -722,7 +728,7 @@@ int checkout_fast_forward(const unsigne opts.verbose_update = 1; opts.merge = 1; opts.fn = twoway_merge; - opts.msgs = get_porcelain_error_msgs(); + setup_unpack_trees_porcelain(&opts, "merge"); trees[nr_trees] = parse_tree_indirect(head); if (!trees[nr_trees++]) @@@ -822,7 -834,7 +840,7 @@@ static int finish_automerge(struct comm return 0; } -static int suggest_conflicts(void) +static int suggest_conflicts(int renormalizing) { FILE *fp; int pos; @@@ -985,7 -997,7 +1003,7 @@@ int cmd_merge(int argc, const char **ar die("%s - not something we can merge", argv[0]); update_ref("initial pull", "HEAD", remote_head->sha1, NULL, 0, DIE_ON_ERR); - reset_hard(remote_head->sha1, 0); + read_empty(remote_head->sha1, 0); return 0; } else { struct strbuf merge_names = STRBUF_INIT; @@@ -1004,12 -1016,14 +1022,12 @@@ for (i = 0; i < argc; i++) merge_name(argv[i], &merge_names); - if (have_message && option_log) - fmt_merge_msg_shortlog(&merge_names, &merge_msg); - else if (!have_message) - fmt_merge_msg(option_log, &merge_names, &merge_msg); - - - if (!(have_message && !option_log) && merge_msg.len) - strbuf_setlen(&merge_msg, merge_msg.len-1); + if (!have_message || shortlog_len) { + fmt_merge_msg(&merge_names, &merge_msg, !have_message, + shortlog_len); + if (merge_msg.len) + strbuf_setlen(&merge_msg, merge_msg.len - 1); + } } if (head_invalid || !argc) @@@ -1305,5 -1319,5 +1323,5 @@@ "stopped before committing as requested\n"); return 0; } else - return suggest_conflicts(); + return suggest_conflicts(option_renormalize); } diff --combined t/t7607-merge-overwrite.sh index d82349a6a,8317a574c..3988900fc --- a/t/t7607-merge-overwrite.sh +++ b/t/t7607-merge-overwrite.sh @@@ -31,7 -31,7 +31,7 @@@ test_expect_success 'setup' test_expect_success 'will not overwrite untracked file' ' git reset --hard c1 && cat important > c2.c && - ! git merge c2 && + test_must_fail git merge c2 && test_cmp important c2.c ' @@@ -39,7 -39,7 +39,7 @@@ test_expect_success 'will not overwrit git reset --hard c1 && cat important > c2.c && git add c2.c && - ! git merge c2 && + test_must_fail git merge c2 && test_cmp important c2.c ' @@@ -48,7 -48,7 +48,7 @@@ test_expect_success 'will not overwrit cat important > c2.c && git add c2.c && rm c2.c && - ! git merge c2 && + test_must_fail git merge c2 && git checkout c2.c && test_cmp important c2.c ' @@@ -58,7 -58,7 +58,7 @@@ test_expect_success 'will not overwrit git rm c1.c && git commit -m "rm c1.c" && cat important > c1.c && - ! git merge c1a && + test_must_fail git merge c1a && test_cmp important c1.c ' @@@ -68,7 -68,7 +68,7 @@@ test_expect_success 'will not overwrit git commit -m "rm c1.c" && cat important > c1.c && git add c1.c && - ! git merge c1a && + test_must_fail git merge c1a && test_cmp important c1.c ' @@@ -79,9 -79,25 +79,25 @@@ test_expect_success 'will not overwrit cat important > c1.c && git add c1.c && rm c1.c && - ! git merge c1a && + test_must_fail git merge c1a && git checkout c1.c && test_cmp important c1.c ' + cat >expect <<\EOF + error: Untracked working tree file 'c0.c' would be overwritten by merge. + fatal: read-tree failed + EOF + + test_expect_success 'will not overwrite untracked file on unborn branch' ' + git reset --hard c0 && + git rm -fr . && + git checkout --orphan new && + cp important c0.c && + test_must_fail git merge c0 2>out && + test_cmp out expect && + test_path_is_missing .git/MERGE_HEAD && + test_cmp important c0.c + ' + test_done