Similar to automatic detach, this behavior could be confusing because
it can sometimes create a new branch without a user asking it to,
especially when the user is still not aware about this feature.

In the future, perhaps we could have a config key to disable these
safety nets and let 'switch' do automatic detach or dwim
again. But that will be opt-in after the user knows what is what. For
now give a short option if you want to use it often.
---
 Documentation/git-checkout.txt | 38 ++++++++++++++++++++--------------
 builtin/checkout.c             | 16 +++++++-------
 2 files changed, 31 insertions(+), 23 deletions(-)

diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt
index ac355dc3f3..2b776c1269 100644
--- a/Documentation/git-checkout.txt
+++ b/Documentation/git-checkout.txt
@@ -31,22 +31,13 @@ branch.
        `<branch>`.
 +
 If `<branch>` is not found but there does exist a tracking branch in
-exactly one remote (call it `<remote>`) with a matching name, treat as
-equivalent to
+exactly one remote (call it `<remote>`) with a matching name and
+`--no-guess` is not specified, treat as equivalent to
 +
 ------------
 $ git checkout -b <branch> --track <remote>/<branch>
 ------------
 +
-If the branch exists in multiple remotes and one of them is named by
-the `checkout.defaultRemote` configuration variable, we'll use that
-one for the purposes of disambiguation, even if the `<branch>` isn't
-unique across all remotes. Set it to
-e.g. `checkout.defaultRemote=origin` to always checkout remote
-branches from there if `<branch>` is ambiguous but exists on the
-'origin' remote. See also `checkout.defaultRemote` in
-linkgit:git-config[1].
-+
 You could omit `<branch>`, in which case the command degenerates to
 "check out the current branch", which is a glorified no-op with
 rather expensive side-effects to show only the tracking information,
@@ -183,6 +174,27 @@ explicitly give a name with `-b` in such a case.
        Do not set up "upstream" configuration, even if the
        branch.autoSetupMerge configuration variable is true.
 
+--guess::
+--no-guess::
+       If `<branch>` is not found but there does exist a tracking
+       branch in exactly one remote (call it `<remote>`) with a
+       matching name, treat as equivalent to
++
+------------
+$ git checkout -b <branch> --track <remote>/<branch>
+------------
++
+If the branch exists in multiple remotes and one of them is named by
+the `checkout.defaultRemote` configuration variable, we'll use that
+one for the purposes of disambiguation, even if the `<branch>` isn't
+unique across all remotes. Set it to
+e.g. `checkout.defaultRemote=origin` to always checkout remote
+branches from there if `<branch>` is ambiguous but exists on the
+'origin' remote. See also `checkout.defaultRemote` in
+linkgit:git-config[1].
++
+Use `--no-guess` to disable this.
+
 -l::
        Create the new branch's reflog; see linkgit:git-branch[1] for
        details.
@@ -287,10 +299,6 @@ Note that this option uses the no overlay mode by default 
(see also
        Just like linkgit:git-submodule[1], this will detach the
        submodules HEAD.
 
---no-guess::
-       Do not attempt to create a branch if a remote tracking branch
-       of the same name exists.
-
 --overlay::
 --no-overlay::
        In the default overlay mode, `git checkout` never
diff --git a/builtin/checkout.c b/builtin/checkout.c
index 0866aeba83..8a89df4f36 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -53,7 +53,7 @@ struct checkout_opts {
        int show_progress;
        int count_checkout_paths;
        int overlay_mode;
-       int no_dwim_new_local_branch;
+       int dwim_new_local_branch;
        int accept_pathspec;
        int switch_branch_doing_nothing_is_ok;
 
@@ -1403,8 +1403,6 @@ static struct option *add_common_switch_branch_options(
                OPT_BOOL_F(0, "overwrite-ignore", &opts->overwrite_ignore,
                           N_("update ignored files (default)"),
                           PARSE_OPT_NOCOMPLETE),
-               OPT_BOOL(0, "no-guess", &opts->no_dwim_new_local_branch,
-                        N_("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")),
                OPT_END()
@@ -1441,7 +1439,6 @@ static int checkout_main(int argc, const char **argv, 
const char *prefix,
 {
        struct branch_info new_branch_info;
        int dwim_remotes_matched = 0;
-       int dwim_new_local_branch;
 
        memset(&new_branch_info, 0, sizeof(new_branch_info));
        opts->overwrite_ignore = 1;
@@ -1456,7 +1453,6 @@ static int checkout_main(int argc, const char **argv, 
const char *prefix,
        argc = parse_options(argc, argv, prefix, options, usagestr,
                             PARSE_OPT_KEEP_DASHDASH);
 
-       dwim_new_local_branch = !opts->no_dwim_new_local_branch;
        if (opts->show_progress < 0) {
                if (opts->quiet)
                        opts->show_progress = 0;
@@ -1516,7 +1512,7 @@ static int checkout_main(int argc, const char **argv, 
const char *prefix,
                struct object_id rev;
                int dwim_ok =
                        !opts->patch_mode &&
-                       dwim_new_local_branch &&
+                       opts->dwim_new_local_branch &&
                        opts->track == BRANCH_TRACK_UNSPECIFIED &&
                        !opts->new_branch;
                int n = parse_branchname_arg(argc, argv, dwim_ok,
@@ -1597,12 +1593,14 @@ int cmd_checkout(int argc, const char **argv, const 
char *prefix)
                OPT_STRING('B', NULL, &opts.new_branch_force, N_("branch"),
                           N_("create/reset and checkout a branch")),
                OPT_BOOL('l', NULL, &opts.new_branch_log, N_("create reflog for 
new branch")),
+               OPT_BOOL(0, "guess", &opts.dwim_new_local_branch,
+                        N_("second guess 'git checkout <no-such-branch>' 
(default)")),
                OPT_END()
        };
        int ret;
 
        memset(&opts, 0, sizeof(opts));
-       opts.no_dwim_new_local_branch = 0;
+       opts.dwim_new_local_branch = 1;
        opts.switch_branch_doing_nothing_is_ok = 1;
        opts.accept_pathspec = 1;
        opts.implicit_detach = 1;
@@ -1627,12 +1625,14 @@ int cmd_switch(int argc, const char **argv, const char 
*prefix)
                           N_("create and switch to a new branch")),
                OPT_STRING('C', "force-create", &opts.new_branch_force, 
N_("branch"),
                           N_("create/reset and switch to a branch")),
+               OPT_BOOL('g', "guess", &opts.dwim_new_local_branch,
+                        N_("second guess 'git switch <no-such-branch>'")),
                OPT_END()
        };
        int ret;
 
        memset(&opts, 0, sizeof(opts));
-       opts.no_dwim_new_local_branch = 0;
+       opts.dwim_new_local_branch = 0;
        opts.accept_pathspec = 0;
        opts.switch_branch_doing_nothing_is_ok = 0;
        opts.implicit_detach = 0;
-- 
2.21.0.rc1.337.gdf7f8d0522

Reply via email to