Merge branch 'cb/maint-orphan-merge-noclobber' into maint
authorJunio C Hamano <gitster@pobox.com>
Thu, 2 Dec 2010 19:27:13 +0000 (11:27 -0800)
committerJunio C Hamano <gitster@pobox.com>
Thu, 2 Dec 2010 19:27:13 +0000 (11:27 -0800)
* cb/maint-orphan-merge-noclobber:
do not overwrite untracked during merge from unborn branch

1  2 
builtin/merge.c
t/t7607-merge-overwrite.sh
diff --combined builtin/merge.c
index 5f65c0c8a6eacd4c6d05602ad9de2821ec62a034,2a6c49f6ce4209fdc59b18498c58399f17044d79..d0bd651725648c01e2c4250f2533aed2c8174164
@@@ -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;
  }
  
@@@ -233,6 -231,24 +233,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;
@@@ -439,7 -455,7 +457,7 @@@ static void merge_name(const char *remo
                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),
@@@ -488,8 -504,7 +506,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++;
                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);
        return git_diff_ui_config(k, v, cb);
  }
  
@@@ -629,11 -642,6 +647,11 @@@ static int try_merge_strategy(const cha
                if (!strcmp(strategy, "subtree"))
                        o.subtree_shift = "";
  
 +              o.renormalize = option_renormalize;
 +
 +              /*
 +               * NEEDSWORK: merge with table in builtin/merge-recursive
 +               */
                for (x = 0; x < xopts_nr; x++) {
                        if (!strcmp(xopts[x], "ours"))
                                o.recursive_variant = MERGE_RECURSIVE_OURS;
                                o.subtree_shift = "";
                        else if (!prefixcmp(xopts[x], "subtree="))
                                o.subtree_shift = xopts[x]+8;
 +                      else if (!strcmp(xopts[x], "renormalize"))
 +                              o.renormalize = 1;
 +                      else if (!strcmp(xopts[x], "no-renormalize"))
 +                              o.renormalize = 0;
                        else
                                die("Unknown option for merge-recursive: -X%s", xopts[x]);
                }
@@@ -718,7 -722,7 +736,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++])
@@@ -830,7 -834,7 +848,7 @@@ static int finish_automerge(struct comm
        return 0;
  }
  
 -static int suggest_conflicts(void)
 +static int suggest_conflicts(int renormalizing)
  {
        FILE *fp;
        int pos;
@@@ -993,7 -997,7 +1011,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;
                        "stopped before committing as requested\n");
                return 0;
        } else
 -              return suggest_conflicts();
 +              return suggest_conflicts(option_renormalize);
  }
index d82349a6a8d6c12c3ca4398a18bd6c1dd42efdc9,8317a574ce2a56162094e817499fb188043ba8da..3988900fc33f0f5f9cdd416096df619aec2d577e
@@@ -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