Subject: Re: resolving a (possibly remote) branch HEAD to a hash

From: Junio C Hamano <[email-masked]>
Date: Mon, 10 Aug 2015 11:41:45 -0700

[email-masked] (Perry Hutchison) writes:

>> ... we do not say "append 'refs/remotes/<anything>/' for various
>> values of <anything> and see if such a ref exists" when resolving
>> an abbreviated refname 'master'.
>
> checkout appears to.

You are referring to this part of the documentation:

    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>

A reader needs to read this part of the documentation a bit more
carefully in order to notice that it never says it is equivalent to:

        $ git checkout -b <branch> -t <branch> ;# NOT CORRECT

This behaviour was brought in by somebody who thought that, in the
context of "checkout" (and only in that context), it is clear that
missing <branch> that can only mean the sole <remote>/<branch> and
make that signal something more than what the user told "checkout"
to do: "If you want to check out a <branch>, and it does not exist
yet, you must wanted to create your own <branch> and start it at the
same commit as somebody else has at the tip of his <branch>".

This "clever" dwim is very specific to the way you interact with
"checkout" and generally does not apply when you want to run
anything other than "checkout", e.g. "rev-parse" or "log".

But it is _so_ convenient a short-cut, that it lets new people form
into an illusion that <branch> could be naming <remote>/<branch>.
That is an incorrect perception.

The rationale behind "signal something more" above goes like this:
if the user wanted to detach the head at the same commit as somebody
else's <branch>, she would explicitly have written

	$ git checkout <remote>/<branch>

to do so.  Because <remote>/<branch> is the shortest valid way to
name that remote-tracking branch (i.e. exactly because <branch> is
not a valid abbreviation for <remote>/<branch>), we can treat

	$ git checkout <branch>

when <branch> is not a local branch name specially.

It is sad and ironic that this checkout-specific DWIM works only
because <branch> does not mean <remote>/<branch>, but presence of
the DWIM gives a wrong illusion that it does X-<.