Merge branch 'nd/checkout-dwim-fix'
"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
This commit is contained in:
@ -276,6 +276,10 @@ section of linkgit:git-add[1] to learn how to operate the `--patch` mode.
|
|||||||
Just like linkgit:git-submodule[1], this will detach the
|
Just like linkgit:git-submodule[1], this will detach the
|
||||||
submodules HEAD.
|
submodules HEAD.
|
||||||
|
|
||||||
|
--no-guess::
|
||||||
|
Do not attempt to create a branch if a remote tracking branch
|
||||||
|
of the same name exists.
|
||||||
|
|
||||||
<branch>::
|
<branch>::
|
||||||
Branch to checkout; if it refers to a branch (i.e., a name that,
|
Branch to checkout; if it refers to a branch (i.e., a name that,
|
||||||
when prepended with "refs/heads/", is a valid ref), then that
|
when prepended with "refs/heads/", is a valid ref), then that
|
||||||
|
@ -1080,9 +1080,12 @@ static int parse_branchname_arg(int argc, const char **argv,
|
|||||||
*/
|
*/
|
||||||
int recover_with_dwim = dwim_new_local_branch_ok;
|
int recover_with_dwim = dwim_new_local_branch_ok;
|
||||||
|
|
||||||
if (!has_dash_dash &&
|
int could_be_checkout_paths = !has_dash_dash &&
|
||||||
(check_filename(opts->prefix, arg) || !no_wildcard(arg)))
|
check_filename(opts->prefix, arg);
|
||||||
|
|
||||||
|
if (!has_dash_dash && !no_wildcard(arg))
|
||||||
recover_with_dwim = 0;
|
recover_with_dwim = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Accept "git checkout foo" and "git checkout foo --"
|
* Accept "git checkout foo" and "git checkout foo --"
|
||||||
* as candidates for dwim.
|
* as candidates for dwim.
|
||||||
@ -1095,6 +1098,10 @@ static int parse_branchname_arg(int argc, const char **argv,
|
|||||||
const char *remote = unique_tracking_name(arg, rev,
|
const char *remote = unique_tracking_name(arg, rev,
|
||||||
dwim_remotes_matched);
|
dwim_remotes_matched);
|
||||||
if (remote) {
|
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;
|
*new_branch = arg;
|
||||||
arg = remote;
|
arg = remote;
|
||||||
/* DWIMmed to create local branch, case (3).(b) */
|
/* DWIMmed to create local branch, case (3).(b) */
|
||||||
@ -1229,7 +1236,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
|
|||||||
struct checkout_opts opts;
|
struct checkout_opts opts;
|
||||||
struct branch_info new_branch_info;
|
struct branch_info new_branch_info;
|
||||||
char *conflict_style = NULL;
|
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;
|
int dwim_remotes_matched = 0;
|
||||||
struct option options[] = {
|
struct option options[] = {
|
||||||
OPT__QUIET(&opts.quiet, N_("suppress progress reporting")),
|
OPT__QUIET(&opts.quiet, N_("suppress progress reporting")),
|
||||||
@ -1259,8 +1266,8 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
|
|||||||
OPT_BOOL('p', "patch", &opts.patch_mode, N_("select hunks interactively")),
|
OPT_BOOL('p', "patch", &opts.patch_mode, N_("select hunks interactively")),
|
||||||
OPT_BOOL(0, "ignore-skip-worktree-bits", &opts.ignore_skipworktree,
|
OPT_BOOL(0, "ignore-skip-worktree-bits", &opts.ignore_skipworktree,
|
||||||
N_("do not limit pathspecs to sparse entries only")),
|
N_("do not limit pathspecs to sparse entries only")),
|
||||||
OPT_HIDDEN_BOOL(0, "guess", &dwim_new_local_branch,
|
OPT_BOOL(0, "no-guess", &no_dwim_new_local_branch,
|
||||||
N_("second guess 'git checkout <no-such-branch>'")),
|
N_("do not second guess 'git checkout <no-such-branch>'")),
|
||||||
OPT_BOOL(0, "ignore-other-worktrees", &opts.ignore_other_worktrees,
|
OPT_BOOL(0, "ignore-other-worktrees", &opts.ignore_other_worktrees,
|
||||||
N_("do not check if another worktree is holding the given ref")),
|
N_("do not check if another worktree is holding the given ref")),
|
||||||
{ OPTION_CALLBACK, 0, "recurse-submodules", NULL,
|
{ OPTION_CALLBACK, 0, "recurse-submodules", NULL,
|
||||||
@ -1283,6 +1290,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
|
|||||||
argc = parse_options(argc, argv, prefix, options, checkout_usage,
|
argc = parse_options(argc, argv, prefix, options, checkout_usage,
|
||||||
PARSE_OPT_KEEP_DASHDASH);
|
PARSE_OPT_KEEP_DASHDASH);
|
||||||
|
|
||||||
|
dwim_new_local_branch = !no_dwim_new_local_branch;
|
||||||
if (opts.show_progress < 0) {
|
if (opts.show_progress < 0) {
|
||||||
if (opts.quiet)
|
if (opts.quiet)
|
||||||
opts.show_progress = 0;
|
opts.show_progress = 0;
|
||||||
|
@ -278,4 +278,35 @@ test_expect_success 'loosely defined local base branch is reported correctly' '
|
|||||||
test_cmp expect actual
|
test_cmp expect actual
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'reject when arg could be part of dwim branch' '
|
||||||
|
git remote add foo file://non-existent-place &&
|
||||||
|
git update-ref refs/remotes/foo/dwim-arg HEAD &&
|
||||||
|
echo foo >dwim-arg &&
|
||||||
|
git add dwim-arg &&
|
||||||
|
echo bar >dwim-arg &&
|
||||||
|
test_must_fail git checkout dwim-arg &&
|
||||||
|
test_must_fail git rev-parse refs/heads/dwim-arg -- &&
|
||||||
|
grep bar dwim-arg
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'disambiguate dwim branch and checkout path (1)' '
|
||||||
|
git update-ref refs/remotes/foo/dwim-arg1 HEAD &&
|
||||||
|
echo foo >dwim-arg1 &&
|
||||||
|
git add dwim-arg1 &&
|
||||||
|
echo bar >dwim-arg1 &&
|
||||||
|
git checkout -- dwim-arg1 &&
|
||||||
|
test_must_fail git rev-parse refs/heads/dwim-arg1 -- &&
|
||||||
|
grep foo dwim-arg1
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'disambiguate dwim branch and checkout path (2)' '
|
||||||
|
git update-ref refs/remotes/foo/dwim-arg2 HEAD &&
|
||||||
|
echo foo >dwim-arg2 &&
|
||||||
|
git add dwim-arg2 &&
|
||||||
|
echo bar >dwim-arg2 &&
|
||||||
|
git checkout dwim-arg2 -- &&
|
||||||
|
git rev-parse refs/heads/dwim-arg2 -- &&
|
||||||
|
grep bar dwim-arg2
|
||||||
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
@ -1434,7 +1434,8 @@ test_expect_success 'double dash "git checkout"' '
|
|||||||
--ignore-other-worktrees Z
|
--ignore-other-worktrees Z
|
||||||
--recurse-submodules Z
|
--recurse-submodules Z
|
||||||
--progress Z
|
--progress Z
|
||||||
--no-quiet Z
|
--guess Z
|
||||||
|
--no-guess Z
|
||||||
--no-... Z
|
--no-... Z
|
||||||
EOF
|
EOF
|
||||||
'
|
'
|
||||||
|
Reference in New Issue
Block a user