switch: implicit dwim, use --no-guess to disable it

This is already the default in git-checkout. The real change in here is just minor cleanup. The main excuse is to explain why dwim is kept default. Contrary to detach mode that is easy to get into and confusing to get back out. Automatically creating a tracking branch often does not kick in as often (you would need a branch of the same name on a remote). And since the branch creation is reported clearly, the user should be able to undo/delete it if it's unwanted. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Nguyễn Thái Ngọc Duy committed Mar 29, 2019 at 17:39 UTC ccb111b342f472d12baddbfa5b52810da1725ffd
2 files changed +31 -23
Documentation/git-checkout.txt
+23 -15
@@ -31,22 +31,13 @@ branch.
31 `<branch>`.
32 +
33 If `<branch>` is not found but there does exist a tracking branch in
34 -exactly one remote (call it `<remote>`) with a matching name, treat as
35 -equivalent to
34 +exactly one remote (call it `<remote>`) with a matching name and
35 +`--no-guess` is not specified, treat as equivalent to
36 +
37 ------------
38 $ git checkout -b <branch> --track <remote>/<branch>
39 ------------
40 +
41 -If the branch exists in multiple remotes and one of them is named by
42 -the `checkout.defaultRemote` configuration variable, we'll use that
43 -one for the purposes of disambiguation, even if the `<branch>` isn't
44 -unique across all remotes. Set it to
45 -e.g. `checkout.defaultRemote=origin` to always checkout remote
46 -branches from there if `<branch>` is ambiguous but exists on the
47 -'origin' remote. See also `checkout.defaultRemote` in
48 -linkgit:git-config[1].
49 -+
41 You could omit `<branch>`, in which case the command degenerates to
42 "check out the current branch", which is a glorified no-op with
43 rather expensive side-effects to show only the tracking information,
@@ -183,6 +174,27 @@ explicitly give a name with `-b` in such a case.
174 Do not set up "upstream" configuration, even if the
175 `branch.autoSetupMerge` configuration variable is true.
176
177 +--guess::
178 +--no-guess::
179 + If `<branch>` is not found but there does exist a tracking
180 + branch in exactly one remote (call it `<remote>`) with a
181 + matching name, treat as equivalent to
182 ++
183 +------------
184 +$ git checkout -b <branch> --track <remote>/<branch>
185 +------------
186 ++
187 +If the branch exists in multiple remotes and one of them is named by
188 +the `checkout.defaultRemote` configuration variable, we'll use that
189 +one for the purposes of disambiguation, even if the `<branch>` isn't
190 +unique across all remotes. Set it to
191 +e.g. `checkout.defaultRemote=origin` to always checkout remote
192 +branches from there if `<branch>` is ambiguous but exists on the
193 +'origin' remote. See also `checkout.defaultRemote` in
194 +linkgit:git-config[1].
195 ++
196 +Use `--no-guess` to disable this.
197 +
198 -l::
199 Create the new branch's reflog; see linkgit:git-branch[1] for
200 details.
@@ -287,10 +299,6 @@ Note that this option uses the no overlay mode by default (see also
299 Just like linkgit:git-submodule[1], this will detach `HEAD` of the
300 submodule.
301
290 ---no-guess::
291 - Do not attempt to create a branch if a remote tracking branch
292 - of the same name exists.
293 -
302 --overlay::
303 --no-overlay::
304 In the default overlay mode, `git checkout` never
builtin/checkout.c
+8 -8
@@ -53,7 +53,7 @@ struct checkout_opts {
53 int show_progress;
54 int count_checkout_paths;
55 int overlay_mode;
56 - int no_dwim_new_local_branch;
56 + int dwim_new_local_branch;
57 int discard_changes;
58 int accept_pathspec;
59 int switch_branch_doing_nothing_is_ok;
@@ -1430,8 +1430,6 @@ static struct option *add_common_switch_branch_options(
1430 OPT_BOOL_F(0, "overwrite-ignore", &opts->overwrite_ignore,
1431 N_("update ignored files (default)"),
1432 PARSE_OPT_NOCOMPLETE),
1433 - OPT_BOOL(0, "no-guess", &opts->no_dwim_new_local_branch,
1434 - N_("second guess 'git checkout <no-such-branch>'")),
1433 OPT_BOOL(0, "ignore-other-worktrees", &opts->ignore_other_worktrees,
1434 N_("do not check if another worktree is holding the given ref")),
1435 OPT_END()
@@ -1468,7 +1466,6 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
1466 {
1467 struct branch_info new_branch_info;
1468 int dwim_remotes_matched = 0;
1471 - int dwim_new_local_branch;
1469
1470 memset(&new_branch_info, 0, sizeof(new_branch_info));
1471 opts->overwrite_ignore = 1;
@@ -1483,7 +1480,6 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
1480 argc = parse_options(argc, argv, prefix, options, usagestr,
1481 PARSE_OPT_KEEP_DASHDASH);
1482
1486 - dwim_new_local_branch = !opts->no_dwim_new_local_branch;
1483 if (opts->show_progress < 0) {
1484 if (opts->quiet)
1485 opts->show_progress = 0;
@@ -1545,7 +1541,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
1541 struct object_id rev;
1542 int dwim_ok =
1543 !opts->patch_mode &&
1548 - dwim_new_local_branch &&
1544 + opts->dwim_new_local_branch &&
1545 opts->track == BRANCH_TRACK_UNSPECIFIED &&
1546 !opts->new_branch;
1547 int n = parse_branchname_arg(argc, argv, dwim_ok,
@@ -1626,12 +1622,14 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
1622 OPT_STRING('B', NULL, &opts.new_branch_force, N_("branch"),
1623 N_("create/reset and checkout a branch")),
1624 OPT_BOOL('l', NULL, &opts.new_branch_log, N_("create reflog for new branch")),
1625 + OPT_BOOL(0, "guess", &opts.dwim_new_local_branch,
1626 + N_("second guess 'git checkout <no-such-branch>' (default)")),
1627 OPT_END()
1628 };
1629 int ret;
1630
1631 memset(&opts, 0, sizeof(opts));
1634 - opts.no_dwim_new_local_branch = 0;
1632 + opts.dwim_new_local_branch = 1;
1633 opts.switch_branch_doing_nothing_is_ok = 1;
1634 opts.accept_pathspec = 1;
1635 opts.implicit_detach = 1;
@@ -1656,6 +1654,8 @@ int cmd_switch(int argc, const char **argv, const char *prefix)
1654 N_("create and switch to a new branch")),
1655 OPT_STRING('C', "force-create", &opts.new_branch_force, N_("branch"),
1656 N_("create/reset and switch to a branch")),
1657 + OPT_BOOL(0, "guess", &opts.dwim_new_local_branch,
1658 + N_("second guess 'git switch <no-such-branch>'")),
1659 OPT_BOOL(0, "discard-changes", &opts.discard_changes,
1660 N_("throw away local modifications")),
1661 OPT_END()
@@ -1663,7 +1663,7 @@ int cmd_switch(int argc, const char **argv, const char *prefix)
1663 int ret;
1664
1665 memset(&opts, 0, sizeof(opts));
1666 - opts.no_dwim_new_local_branch = 0;
1666 + opts.dwim_new_local_branch = 1;
1667 opts.accept_pathspec = 0;
1668 opts.switch_branch_doing_nothing_is_ok = 0;
1669 opts.implicit_detach = 0;