Jonathan Nieder [off-list ref] writes:
Junio C Hamano wrote:
quoted
I can see why this is confusing, though.
Dun Peal [off-list ref] writes:
quoted
$ 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?
That looks simpler than what I just did. Can we have a few tests, too?
quoted hunk
-- 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 [off-list ref]
Signed-off-by: Jonathan Nieder <redacted>
---
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 */