threads / bug / 48591

Is origin/HEAD only being created on clone a bug? #leftoverbits

Subject: Is origin/HEAD only being created on clone a bug? #leftoverbits

## tl;dr

7 messages between May 29, 2018 and Jun 1, 2018.

replies: 6people: 4as markdown or json

Ævar Arnfjörð Bjarmason· May 29, 2018, 18:30 UTC · lore

Here's some more #leftoverbits where we have a clone/fetch feature discrepancy and where clone is magical in ways that "fetch" isn't.

If you make an initial commit and push to a remote repo "origin", you don't get a remote origin/HEAD reference, and a "fetch" won't create it either.

You will get it if you subseuqently "clone" the repo, but not if you use "git init / remote add / fetch / git checkout -t" which should otherwise be equivalent.

If you push to "master" (or whatever HEAD is) from the clone the origin/HEAD will be updated accordingly, but from the repo you pushed from & the one you did init+fetch instead of clone you'll never see it.

Some code spelunking reveals remote_head_points_at, guess_remote_head() etc. in builtin/clone.c. I.e. this is special-cased as part of the "clone".

Can anyone thing of a reason for why this shouldn't be fixed as a bug? I've tried searching the archives but "origin/HEAD" comes up with too many results. https://public-inbox.org/git/alpine.LSU.1.00.0803020556380.22527@racer.site/#t seems to be the patch that initially added it, but it is not discussed why this should be a clone-only special case that doesn't apply to "fetch".

Brandon Williams· May 29, 2018, 19:17 UTC · re: Ævar Arnfjörð Bjarmason · lore

Re: Is origin/HEAD only being created on clone a bug? #leftoverbits

On 05/29, Ævar Arnfjörð Bjarmason wrote:
Show 26 quoted lines
> Here's some more #leftoverbits where we have a clone/fetch feature
> discrepancy and where clone is magical in ways that "fetch" isn't.
> 
> If you make an initial commit and push to a remote repo "origin", you
> don't get a remote origin/HEAD reference, and a "fetch" won't create it
> either.
> 
> You will get it if you subseuqently "clone" the repo, but not if you use
> "git init / remote add / fetch / git checkout -t" which should otherwise
> be equivalent.
> 
> If you push to "master" (or whatever HEAD is) from the clone the
> origin/HEAD will be updated accordingly, but from the repo you pushed
> from & the one you did init+fetch instead of clone you'll never see it.
> 
> Some code spelunking reveals remote_head_points_at, guess_remote_head()
> etc. in builtin/clone.c. I.e. this is special-cased as part of the
> "clone".
> 
> Can anyone thing of a reason for why this shouldn't be fixed as a bug?
> I've tried searching the archives but "origin/HEAD" comes up with too
> many
> results. https://public-inbox.org/git/alpine.LSU.1.00.0803020556380.22527@racer.site/#t
> seems to be the patch that initially added it, but it is not discussed
> why this should be a clone-only special case that doesn't apply to
> "fetch".

I believe the issue has to deal with how symrefs are handled. I don't think any of the fetch code path does anything special with symrefs. Symref info does get sent over the wire for the HEAD symref but i think its just ignored. You'll see updates for origin/HEAD when you subsequently fetch most likely because its recorded as a symref locally which points at origin/master. This means that when you fetch origin/master, origin/HEAD will also but updated just because its locally a pointer to origin/master.

With that said, yes we should probably fix this issue with fetch because I added symref support to protocol v2 so now symref information for refs other than HEAD can be sent across the wire but the client just throws that info away at the moment.

-- 
Brandon Williams
Junio C Hamano· May 30, 2018, 01:24 UTC · re: Ævar Arnfjörð Bjarmason · lore

Re: Is origin/HEAD only being created on clone a bug? #leftoverbits

Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
Show 7 quoted lines
> If you make an initial commit and push to a remote repo "origin", you
> don't get a remote origin/HEAD reference, and a "fetch" won't create it
> either.
> ...
> Some code spelunking reveals remote_head_points_at, guess_remote_head()
> etc. in builtin/clone.c. I.e. this is special-cased as part of the
> "clone".

Correct. Originally, there was *no* way in the protocol to carry the information, so the code always had to guess. The point of setting origin/HEAD was mostly so that you can say "log origin.." and rely on it getting dwimmed down to "refs/remotes/%s/HEAD..", and it wasn't a common practice to interact with multiple remotes with remote tracking branches (integrator interacting with dozens of remotes, responding to pull requests using explicit URL but without configured remotes was not uncommon), so it was sufficient for "git clone" to create it, and "git remote add" did not exist back then anyway.

There are two aspects in my answer to your question.
 - If we create additional remote (that is, other than the one we
   get when we create a repository via "clone", so if your "origin"
   is from "git init there && cd there && git remote add origin", it
   does count in this category), should we get a remote-tracking
   symref $name/HEAD so that we can say "log $name.."?  
   We absolutely should.  We (eh, rather, those who added "remote
   add"; this was not my itch and I am using "royal we" in this
   sentence) just did not bother to and I think it is a bug that you
   cannot say "log $name.."  Of course, it is just a "git symbolic-ref"
   away to make it possible locally, so it is understandable if
   "remote add" did not bother to.
 - When we fetch from a remote that has refs/remotes/$name/HEAD, and
   if the protocol notices that their HEAD today is pointing to a
   branch different from what our side has, should we repoint ours
   to match?  
   I am leaning against doing this, but mostly out of superstition.
   Namely, I feel uneasy about the fact that the meaning of "log
   ..origin" changes across a fetch in this sequence:
     log ..origin && fetch origin && log ..origin
   Without repointing origin/HEAD, two occurrences of "log ..origin"
   both means "how much ahead the primary branch we have been
   interested in from this remote is, relative to our effort?".
   Even though we fully expect that two "log ..origin" would report
   different results (after all, that is the whole point of doing
   another one after "fetch" in such a sequence like this example),
   our question is about the same "primary branch we have been
   interested in".  But once fetch starts messing with where
   origin/HEAD points at, that would no longer be the case, which is
   why I am against doing something magical like that.
Junio C Hamano· May 30, 2018, 02:46 UTC · re: Junio C Hamano · lore

Re: Is origin/HEAD only being created on clone a bug? #leftoverbits

Junio C Hamano <gitster@pobox.com> writes:
Show 10 quoted lines
>  - When we fetch from a remote that has refs/remotes/$name/HEAD, and
>    if the protocol notices that their HEAD today is pointing to a
>    branch different from what our side has, should we repoint ours
>    to match?  
>
>    I am leaning against doing this, but mostly out of superstition.
> ...
>    interested in".  But once fetch starts messing with where
>    origin/HEAD points at, that would no longer be the case, which is
>    why I am against doing something magical like that.

Well, I shouldn't say "I am against" on the last line; rather, "I feel uneasy".

Jeff King· Jun 1, 2018, 06:51 UTC · re: Junio C Hamano · lore

Re: Is origin/HEAD only being created on clone a bug? #leftoverbits

On Wed, May 30, 2018 at 11:46:16AM +0900, Junio C Hamano wrote:
Show 15 quoted lines
> Junio C Hamano <gitster@pobox.com> writes:
> 
> >  - When we fetch from a remote that has refs/remotes/$name/HEAD, and
> >    if the protocol notices that their HEAD today is pointing to a
> >    branch different from what our side has, should we repoint ours
> >    to match?  
> >
> >    I am leaning against doing this, but mostly out of superstition.
> > ...
> >    interested in".  But once fetch starts messing with where
> >    origin/HEAD points at, that would no longer be the case, which is
> >    why I am against doing something magical like that.
> 
> Well, I shouldn't say "I am against" on the last line; rather, "I
> feel uneasy".

I didn't bother to dig up the past discussions, but I am pretty sure we intentionally avoided updating origin/HEAD without an explicit action from the user. Because what the other side considers "the default branch" and what you consider "the default branch" when dealing with the remote are not necessarily the same thing. If we auto-adjust the symref on fetch, we might be undoing the user's previous "git remote set-head" operation.

I don't have any real problem with creating it if it _doesn't_ exist, though. (I think ideally it would get created by "remote add", but that command does not always talk to the remote, so this kind of delayed-create is probably the best we can do).

-Peff
Ævar Arnfjörð Bjarmason· May 31, 2018, 07:42 UTC · re: Junio C Hamano · lore

Re: Is origin/HEAD only being created on clone a bug? #leftoverbits

On Wed, May 30 2018, Junio C Hamano wrote:
Show 57 quoted lines
> Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
>
>> If you make an initial commit and push to a remote repo "origin", you
>> don't get a remote origin/HEAD reference, and a "fetch" won't create it
>> either.
>> ...
>> Some code spelunking reveals remote_head_points_at, guess_remote_head()
>> etc. in builtin/clone.c. I.e. this is special-cased as part of the
>> "clone".
>
> Correct.  Originally, there was *no* way in the protocol to carry
> the information, so the code always had to guess.  The point of
> setting origin/HEAD was mostly so that you can say "log origin.."
> and rely on it getting dwimmed down to "refs/remotes/%s/HEAD..",
> and it wasn't a common practice to interact with multiple remotes
> with remote tracking branches (integrator interacting with dozens
> of remotes, responding to pull requests using explicit URL but
> without configured remotes was not uncommon), so it was sufficient
> for "git clone" to create it, and "git remote add" did not exist
> back then anyway.
>
> There are two aspects in my answer to your question.
>
>  - If we create additional remote (that is, other than the one we
>    get when we create a repository via "clone", so if your "origin"
>    is from "git init there && cd there && git remote add origin", it
>    does count in this category), should we get a remote-tracking
>    symref $name/HEAD so that we can say "log $name.."?
>
>    We absolutely should.  We (eh, rather, those who added "remote
>    add"; this was not my itch and I am using "royal we" in this
>    sentence) just did not bother to and I think it is a bug that you
>    cannot say "log $name.."  Of course, it is just a "git symbolic-ref"
>    away to make it possible locally, so it is understandable if
>    "remote add" did not bother to.
>
>  - When we fetch from a remote that has refs/remotes/$name/HEAD, and
>    if the protocol notices that their HEAD today is pointing to a
>    branch different from what our side has, should we repoint ours
>    to match?
>
>    I am leaning against doing this, but mostly out of superstition.
>    Namely, I feel uneasy about the fact that the meaning of "log
>    ..origin" changes across a fetch in this sequence:
>
>      log ..origin && fetch origin && log ..origin
>
>    Without repointing origin/HEAD, two occurrences of "log ..origin"
>    both means "how much ahead the primary branch we have been
>    interested in from this remote is, relative to our effort?".
>    Even though we fully expect that two "log ..origin" would report
>    different results (after all, that is the whole point of doing
>    another one after "fetch" in such a sequence like this example),
>    our question is about the same "primary branch we have been
>    interested in".  But once fetch starts messing with where
>    origin/HEAD points at, that would no longer be the case, which is
>    why I am against doing something magical like that.

We already have to deal with this special case of origin/HEAD being re-pointed in a repository that we "clone", so we would just do whatever happens to a repository that's cloned.

I.e. the "clone" sets the origin/HEAD up as a one-off, and then keeps updating it on the basis of updating existing refs. We'd similarly set it up as a one-off if we ever "fetch" and notice that the ref doesn't exist yet, and then we'd update it in the same way we update it now.

So this seems like a non-issue to me as far as me coming up with some patch to one-off write the origin/HEAD on the first "fetch", or am I missing something?

Junio C Hamano· Jun 1, 2018, 01:32 UTC · re: Ævar Arnfjörð Bjarmason · lore

Re: Is origin/HEAD only being created on clone a bug? #leftoverbits

Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
> We already have to deal with this special case of origin/HEAD
> being re-pointed in a repository that we "clone", so we would just
> do whatever happens to a repository that's cloned.

OK. Not visiting that issue while we discuss this "origin/HEAD is useful, so create it even for non-initial-clone case" topic makes it simpler to discuss.

← back to recent threads