Merge branch 'nd/checkout-dwim-fix'
authorJunio C Hamano <gitster@pobox.com>
Fri, 4 Jan 2019 21:33:34 +0000 (13:33 -0800)
committerJunio C Hamano <gitster@pobox.com>
Fri, 4 Jan 2019 21:33:34 +0000 (13:33 -0800)
"git checkout frotz" (without any double-dash) avoids ambiguity by
making sure 'frotz' cannot be interpreted as a revision and as a
path at the same time. This safety has been updated to check also
a unique remote-tracking branch 'frotz' in a remote, when dwimming
to create a local branch 'frotz' out of a remote-tracking branch
'frotz' from a remote.

* nd/checkout-dwim-fix:
checkout: disambiguate dwim tracking branches and local files

1  2 
builtin/checkout.c
t/t9902-completion.sh
diff --combined builtin/checkout.c
index 169e7976752be3c161388084bf6aaf46338cc299,4744e8c0a72eae901308e5484a1c6f312e7278b9..08b0ac48f30fd952fe57376a8e8b0d61f8bc1ad6
@@@ -753,8 -753,7 +753,8 @@@ static void update_refs_for_switch(cons
                        free(refname);
                }
                else
 -                      create_branch(opts->new_branch, new_branch_info->name,
 +                      create_branch(the_repository,
 +                                    opts->new_branch, new_branch_info->name,
                                      opts->new_branch_force ? 1 : 0,
                                      opts->new_branch_force ? 1 : 0,
                                      opts->new_branch_log,
                                delete_reflog(old_branch_info->path);
                }
        }
 -      remove_branch_state();
 +      remove_branch_state(the_repository);
        strbuf_release(&msg);
        if (!opts->quiet &&
            (new_branch_info->path || (!opts->force_detach && !strcmp(new_branch_info->name, "HEAD"))))
@@@ -1080,9 -1079,12 +1080,12 @@@ static int parse_branchname_arg(int arg
                 */
                int recover_with_dwim = dwim_new_local_branch_ok;
  
-               if (!has_dash_dash &&
-                   (check_filename(opts->prefix, arg) || !no_wildcard(arg)))
+               int could_be_checkout_paths = !has_dash_dash &&
+                       check_filename(opts->prefix, arg);
+               if (!has_dash_dash && !no_wildcard(arg))
                        recover_with_dwim = 0;
                /*
                 * Accept "git checkout foo" and "git checkout foo --"
                 * as candidates for dwim.
                        const char *remote = unique_tracking_name(arg, rev,
                                                                  dwim_remotes_matched);
                        if (remote) {
+                               if (could_be_checkout_paths)
+                                       die(_("'%s' could be both a local file and a tracking branch.\n"
+                                             "Please use -- (and optionally --no-guess) to disambiguate"),
+                                           arg);
                                *new_branch = arg;
                                arg = remote;
                                /* DWIMmed to create local branch, case (3).(b) */
@@@ -1229,7 -1235,7 +1236,7 @@@ int cmd_checkout(int argc, const char *
        struct checkout_opts opts;
        struct branch_info new_branch_info;
        char *conflict_style = NULL;
-       int dwim_new_local_branch = 1;
+       int dwim_new_local_branch, no_dwim_new_local_branch = 0;
        int dwim_remotes_matched = 0;
        struct option options[] = {
                OPT__QUIET(&opts.quiet, N_("suppress progress reporting")),
                OPT_BOOL('p', "patch", &opts.patch_mode, N_("select hunks interactively")),
                OPT_BOOL(0, "ignore-skip-worktree-bits", &opts.ignore_skipworktree,
                         N_("do not limit pathspecs to sparse entries only")),
-               OPT_HIDDEN_BOOL(0, "guess", &dwim_new_local_branch,
-                               N_("second guess 'git checkout <no-such-branch>'")),
+               OPT_BOOL(0, "no-guess", &no_dwim_new_local_branch,
+                        N_("do not second guess 'git checkout <no-such-branch>'")),
                OPT_BOOL(0, "ignore-other-worktrees", &opts.ignore_other_worktrees,
                         N_("do not check if another worktree is holding the given ref")),
                { OPTION_CALLBACK, 0, "recurse-submodules", NULL,
        argc = parse_options(argc, argv, prefix, options, checkout_usage,
                             PARSE_OPT_KEEP_DASHDASH);
  
+       dwim_new_local_branch = !no_dwim_new_local_branch;
        if (opts.show_progress < 0) {
                if (opts.quiet)
                        opts.show_progress = 0;
diff --combined t/t9902-completion.sh
index 137fdc9bd525bea9d6ccde256ee449ed389255c0,aa92f8523000ffe177aecb6477752de639d2e6d3..6558eee4996e21a64a1b43b5d293cab683686429
@@@ -1249,7 -1249,7 +1249,7 @@@ test_expect_success 'teardown after re
  
  test_path_completion ()
  {
 -      test $# = 2 || error "bug in the test script: not 2 parameters to test_path_completion"
 +      test $# = 2 || BUG "not 2 parameters to test_path_completion"
  
        local cur="$1" expected="$2"
        echo "$expected" >expected &&
@@@ -1434,7 -1434,8 +1434,8 @@@ test_expect_success 'double dash "git c
        --ignore-other-worktrees Z
        --recurse-submodules Z
        --progress Z
-       --no-quiet Z
+       --guess Z
+       --no-guess Z
        --no-... Z
        EOF
  '
@@@ -1539,7 -1540,7 +1540,7 @@@ test_expect_success 'complete tree file
        EOF
  '
  
 -test_expect_success 'send-email' '
 +test_expect_success PERL 'send-email' '
        test_completion "git send-email --cov" "--cover-letter " &&
        test_completion "git send-email ma" "master "
  '
@@@ -1697,8 -1698,7 +1698,8 @@@ test_expect_success 'sourcing the compl
        verbose test -z "$__git_all_commands"
  '
  
 -test_expect_success !GETTEXT_POISON 'sourcing the completion script clears cached merge strategies' '
 +test_expect_success 'sourcing the completion script clears cached merge strategies' '
 +      GIT_TEST_GETTEXT_POISON= &&
        __git_compute_merge_strategies &&
        verbose test -n "$__git_merge_strategies" &&
        . "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&