Re: Inconsistent behavior of the path disambiguator
- From
Jonathan Nieder <jrnieder@gmail.com>
- Date
- Oct 29, 2010, 19:46 UTC
- Message-ID
- <20101029194639.GA1738@burratino>
- In-Reply-To
- <7vbp6c7ski.fsf@alter.siamese.dyndns.org>
Junio C Hamano wrote:
Show 17 quoted lines
> I can see why this is confusing, though. > > Dun Peal <dunpealer@gmail.com> writes: >> $ git checkout foo -- >> fatal: invalid reference: foo > > Immediately after a clone you would have > > refs/heads/master > refs/HEAD -> refs/heads/master > refs/remotes/origin/foo > refs/remotes/origin/whatever-else-you-have > ... > > and there is no commit that you can name with "foo" when asking git to > check out some paths out of, nor there is no branch that you can name with > "foo" when asking git to check out to work on it.
How about something like this? -- 8< -- Subject: checkout: apply Dscho's dwim even with "--" present
git reset and similar commands use -- to disambiguate between revisions and paths on the command line. The same syntax is not necessary to specify a revision to git checkout (for convenience and historical reasons, revisions are preferred over paths), but for consistency it is accepted:
git checkout master --; # check out master branch, not "master" file.
The autovivification of branches introduced by 70c9ac2f1 (DWIM "git checkout frotz" to "git checkout -b frotz origin/frotz", 2009-10-18) is currently disabled by that syntax, for no good reason. Paranoid scripts can still use
git checkout --no-guess master
or even better,
old=$(git rev-parse --verify HEAD) new=$(git rev-parse --verify refs/heads/master^0) git read-tree -m -u --exclude-standard $old $new git symbolic-ref -m "$me: switching branches" HEAD refs/heads/master
Requested-by: Dun Peal <dunpealer@gmail.com> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> ---
diff --git a/builtin/checkout.c b/builtin/checkout.c index 9240faf..1dc3640 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -771,6 +771,12 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) * <ref> must be a valid tree, everything after the '--' must be * a path. * + * Except: with no paths, if <something> does not resolve as + * an object, no -t nor -b was given, and there is a tracking + * branch whose name is <something> in one and only one remote, + * then this is a short-hand to fork local <something> from + * that remote-tracking branch. + * * case 2: git checkout -- [<paths>] * * everything after the '--' must be paths. @@ -808,13 +814,11 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) arg = "@{-1}"; if (get_sha1_mb(arg, rev)) { - if (has_dash_dash) /* case (1) */ - die("invalid reference: %s", arg); if (!patch_mode && dwim_new_local_branch && opts.track == BRANCH_TRACK_UNSPECIFIED && !opts.new_branch && - !check_filename(NULL, arg) && + (has_dash_dash || !check_filename(NULL, arg)) && argc == 1) { const char *remote = unique_tracking_name(arg); if (!remote || get_sha1(remote, rev)) @@ -822,9 +826,11 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) opts.new_branch = arg; arg = remote; /* DWIMmed to create local branch */ - } - else + } else if (has_dash_dash) { /* case (1) */ + die("invalid reference: %s", arg); + } else { goto no_reference; + } } /* we can't end up being in (2) anymore, eat the argument */