{"thread":{"id":"49126","subject":"Syncing HEAD","startedAt":"2018-08-14T20:09:41Z","lastAt":"2018-08-17T16:48:53Z","messageCount":10,"participants":["Christian Couder","Stefan Beller","Jeff King","Brandon Williams","Ævar Arnfjörð Bjarmason","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"355609","messageId":"CAP8UFD0_jpKdcDvNx5CYnmyDMagE_O-E7cef5VthaT_w-=4xsA@mail.gmail.com","threadId":"49126","inReplyTo":null,"subject":"Syncing HEAD","fromName":"Christian Couder","fromEmail":"christian.couder@gmail.com","sentAt":"2018-08-14T20:09:37Z","receivedAt":"2018-08-14T20:09:41Z","isPatch":false,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"Hi,\n\nWhen cloning with --mirror, the clone gets its HEAD initialized with\nthe value HEAD has in its origin remote. After that if HEAD changes in\norigin there is no simple way to sync HEAD at the same time as the\nrefs are synced.\n\nIt looks like the simplest way to sync HEAD is:\n\n1) git remote show origin\n2) parse \"HEAD branch: XXX\" from the output of the above command\n3) git symbolic-ref HEAD refs/heads/XXX\n\nIt looks like it would be quite easy to add an option to `fetch` to\nsync HEAD at the same time as regular refs are synced because every\nfetch from an origin that uses a recent Git contains something like:\n\n19:55:39.304976 pkt-line.c:80           packet:          git< YYYYYYYY\nHEAD\\0multi_ack thin-pack side-band side-band-64k ofs-delta shallow\ndeepen-since deepen-not deepen-relative no-progress include-tag\nmulti_ack_detailed no-done symref=HEAD:refs/heads/test-1\nagent=git/2.18.0\n\nwhich in this example shows that HEAD is a symref to refs/heads/test-1\nin origin.\n\nIs there a reason why no such option already exists? Would it makes\nsense to add one? Is there any reason why it's not a good idea? Or am\nI missing something?\n\nI am asking because GitLab uses HEAD in the bare repos it manages to\nstore the default branch against which the Merge Requests (same thing\nas Pull Requests on GitHub) are created.\n\nSo when people want to keep 2 GitLab hosted repos in sync, GitLab\nneeds to sync HEADs too, not just the refs.\n\nI think this could be useful to other setups than GitLab though.\n\nThanks,\nChristian.\n"},{"id":"355617","messageId":"CAGZ79kZo3TK7O0bb+mKOkeLkp=rFHfFwGS6oispcvHwCEEh=LA@mail.gmail.com","threadId":"49126","inReplyTo":"CAP8UFD0_jpKdcDvNx5CYnmyDMagE_O-E7cef5VthaT_w-=4xsA@mail.gmail.com","subject":"Re: Syncing HEAD","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2018-08-14T20:58:57Z","receivedAt":"2018-08-14T20:59:11Z","isPatch":false,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Tue, Aug 14, 2018 at 1:09 PM Christian Couder\n<christian.couder@gmail.com> wrote:\n>\n> Hi,\n>\n> When cloning with --mirror, the clone gets its HEAD initialized with\n> the value HEAD has in its origin remote. After that if HEAD changes in\n> origin there is no simple way to sync HEAD at the same time as the\n> refs are synced.\n>\n> It looks like the simplest way to sync HEAD is:\n>\n> 1) git remote show origin\n> 2) parse \"HEAD branch: XXX\" from the output of the above command\n> 3) git symbolic-ref HEAD refs/heads/XXX\n>\n> It looks like it would be quite easy to add an option to `fetch` to\n> sync HEAD at the same time as regular refs are synced because every\n> fetch from an origin that uses a recent Git contains something like:\n>\n> 19:55:39.304976 pkt-line.c:80           packet:          git< YYYYYYYY\n> HEAD\\0multi_ack thin-pack side-band side-band-64k ofs-delta shallow\n> deepen-since deepen-not deepen-relative no-progress include-tag\n> multi_ack_detailed no-done symref=HEAD:refs/heads/test-1\n> agent=git/2.18.0\n>\n> which in this example shows that HEAD is a symref to refs/heads/test-1\n> in origin.\n>\n> Is there a reason why no such option already exists? Would it makes\n> sense to add one? Is there any reason why it's not a good idea? Or am\n> I missing something?\n\nI think it is a great idea to add that. IIRC there was some talk when\ndesigning protocol v2 on how fetching of symrefs could be added later\non in the protocol, which is why I cc'd Brandon who did the work there.\n\n> I am asking because GitLab uses HEAD in the bare repos it manages to\n> store the default branch against which the Merge Requests (same thing\n> as Pull Requests on GitHub) are created.\n>\n> So when people want to keep 2 GitLab hosted repos in sync, GitLab\n> needs to sync HEADs too, not just the refs.\n>\n> I think this could be useful to other setups than GitLab though.\n\nAs said, I can see how that is useful; I recently came across some\nHEAD bug related to submodules, and there we'd also have the application.\n\n    git clone --recurse-submodules file://...\n\nmight clone the submodules that are in detached HEAD, which is totally\nnot a long term viable good HEAD, so a subsequent fetch might want\nto change the detached HEAD in submodules or re-affix it to branches.\n\nUnrelated/extended: I think it would be cool to mirror a repository even\nmore, e.g. it would be cool to be able to fetch (if configured as allowed)\nthe remote reflog, (not to be confused with you local reflog of the remote).\nI think that work would be enabled once reftables are available, which you\nhave an eye on?\n"},{"id":"355622","messageId":"20180814210616.GA32367@sigill.intra.peff.net","threadId":"49126","inReplyTo":"CAP8UFD0_jpKdcDvNx5CYnmyDMagE_O-E7cef5VthaT_w-=4xsA@mail.gmail.com","subject":"Re: Syncing HEAD","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2018-08-14T21:06:16Z","receivedAt":"2018-08-14T21:06:21Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Tue, Aug 14, 2018 at 10:09:37PM +0200, Christian Couder wrote:\n\n> When cloning with --mirror, the clone gets its HEAD initialized with\n> the value HEAD has in its origin remote. After that if HEAD changes in\n> origin there is no simple way to sync HEAD at the same time as the\n> refs are synced.\n> \n> It looks like the simplest way to sync HEAD is:\n> \n> 1) git remote show origin\n> 2) parse \"HEAD branch: XXX\" from the output of the above command\n> 3) git symbolic-ref HEAD refs/heads/XXX\n\nHow about:\n\n  git remote set-head origin -a\n\n?\n\n> It looks like it would be quite easy to add an option to `fetch` to\n> sync HEAD at the same time as regular refs are synced because every\n> fetch from an origin that uses a recent Git contains something like:\n\nI think the \"remote set-head\" option is not very discoverable, since\npeople are used to working with \"fetch\", making it the natural place to\nlook. Just like we ported \"remote update\" over to \"fetch --all\", I think\nit would be sensible to have \"fetch --update-head\" or similar.\n\nOne tricky thing is that the name \"refs/remotes/<remote>/HEAD\" is only\nspecial by convention, and that convention is known on the writing side\nonly by git-clone and git-remote. So obviously:\n\n  git fetch --update-head https://example.com/\n\nis nonsense. We don't even have a ref. What should:\n\n  git config remote.origin.fetch refs/heads/*:refs/remotes/foo/*\n  git fetch --update-head origin\n\ndo? Should it update based no the remote name, or based on the refspec?\nWhat happens if there are several refspecs? Etc.\n\n99% of the time those questions won't come up. But we should design so\nthat we do the obvious thing in those 99%, and something sane in the\nother 1%.\n\n-Peff\n"},{"id":"355624","messageId":"20180814210853.GB86804@google.com","threadId":"49126","inReplyTo":"CAGZ79kZo3TK7O0bb+mKOkeLkp=rFHfFwGS6oispcvHwCEEh=LA@mail.gmail.com","subject":"Re: Syncing HEAD","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2018-08-14T21:08:53Z","receivedAt":"2018-08-14T21:08:58Z","isPatch":false,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"On 08/14, Stefan Beller wrote:\n> On Tue, Aug 14, 2018 at 1:09 PM Christian Couder\n> <christian.couder@gmail.com> wrote:\n> >\n> > Hi,\n> >\n> > When cloning with --mirror, the clone gets its HEAD initialized with\n> > the value HEAD has in its origin remote. After that if HEAD changes in\n> > origin there is no simple way to sync HEAD at the same time as the\n> > refs are synced.\n> >\n> > It looks like the simplest way to sync HEAD is:\n> >\n> > 1) git remote show origin\n> > 2) parse \"HEAD branch: XXX\" from the output of the above command\n> > 3) git symbolic-ref HEAD refs/heads/XXX\n> >\n> > It looks like it would be quite easy to add an option to `fetch` to\n> > sync HEAD at the same time as regular refs are synced because every\n> > fetch from an origin that uses a recent Git contains something like:\n> >\n> > 19:55:39.304976 pkt-line.c:80           packet:          git< YYYYYYYY\n> > HEAD\\0multi_ack thin-pack side-band side-band-64k ofs-delta shallow\n> > deepen-since deepen-not deepen-relative no-progress include-tag\n> > multi_ack_detailed no-done symref=HEAD:refs/heads/test-1\n> > agent=git/2.18.0\n> >\n> > which in this example shows that HEAD is a symref to refs/heads/test-1\n> > in origin.\n> >\n> > Is there a reason why no such option already exists? Would it makes\n> > sense to add one? Is there any reason why it's not a good idea? Or am\n> > I missing something?\n> \n> I think it is a great idea to add that. IIRC there was some talk when\n> designing protocol v2 on how fetching of symrefs could be added later\n> on in the protocol, which is why I cc'd Brandon who did the work there.\n\nActually the functionality for fetching symrefs already exists (when\nusing protocol v2 of course).  Despite this functionality existing its\nnot being used right now.\n\nWhen performing a v2 fetch the first thing that a client does is request\nthe list of refs (by doing an ls-refs request).  The output from ls-refs\n(if asked) will included information about each ref including if they\nare a symref and what ref they resolve to.  So really we just need to\nplumb that information through fetch to actually update HEAD, or even\nupdate other symrefs which exist on the server.\n\n> \n> > I am asking because GitLab uses HEAD in the bare repos it manages to\n> > store the default branch against which the Merge Requests (same thing\n> > as Pull Requests on GitHub) are created.\n> >\n> > So when people want to keep 2 GitLab hosted repos in sync, GitLab\n> > needs to sync HEADs too, not just the refs.\n> >\n> > I think this could be useful to other setups than GitLab though.\n> \n> As said, I can see how that is useful; I recently came across some\n> HEAD bug related to submodules, and there we'd also have the application.\n> \n>     git clone --recurse-submodules file://...\n> \n> might clone the submodules that are in detached HEAD, which is totally\n> not a long term viable good HEAD, so a subsequent fetch might want\n> to change the detached HEAD in submodules or re-affix it to branches.\n> \n> Unrelated/extended: I think it would be cool to mirror a repository even\n> more, e.g. it would be cool to be able to fetch (if configured as allowed)\n> the remote reflog, (not to be confused with you local reflog of the remote).\n> I think that work would be enabled once reftables are available, which you\n> have an eye on?\n\n-- \nBrandon Williams\n"},{"id":"355630","messageId":"20180814214723.GA667@sigill.intra.peff.net","threadId":"49126","inReplyTo":"20180814210616.GA32367@sigill.intra.peff.net","subject":"Re: Syncing HEAD","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2018-08-14T21:47:24Z","receivedAt":"2018-08-14T21:47:27Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Tue, Aug 14, 2018 at 05:06:16PM -0400, Jeff King wrote:\n\n> On Tue, Aug 14, 2018 at 10:09:37PM +0200, Christian Couder wrote:\n> \n> > When cloning with --mirror, the clone gets its HEAD initialized with\n> > the value HEAD has in its origin remote. After that if HEAD changes in\n> > origin there is no simple way to sync HEAD at the same time as the\n> > refs are synced.\n> > \n> > It looks like the simplest way to sync HEAD is:\n> > \n> > 1) git remote show origin\n> > 2) parse \"HEAD branch: XXX\" from the output of the above command\n> > 3) git symbolic-ref HEAD refs/heads/XXX\n> \n> How about:\n> \n>   git remote set-head origin -a\n> \n> ?\n\nReading your message again, I see you actually care less about the\nrefs/remote placeholder and more about the actual HEAD in a bare repo.\n\nIn which case \"git remote\" isn't going to help, though its underlying\ncode has the algorithm you would want.\n\n> One tricky thing is that the name \"refs/remotes/<remote>/HEAD\" is only\n> special by convention, and that convention is known on the writing side\n> only by git-clone and git-remote. So obviously:\n\nAnd so here the convention is simpler, because we're talking about the\nmain HEAD. But we still have know if you want to do that, and not update\nsome refs/remotes/ symref in a bare repo.\n\nSo all of this really implies to me that you want to be able to say\n\"take this symref on the other side and update this one on the local\nside\". I.e., some way to tell a refspec \"don't update the value, update\nthe symref destination\". So imagine we made \"~\" the magic character for\n\"just the symrefs\" (I picked that because it's not allowed in a\nrefname).\n\nThen you could do what you want with:\n\n  git config --add remote.origin.fetch ~HEAD:HEAD\n\nand these two would be the same:\n\n  git remote set-head origin -a\n  git fetch origin ~HEAD:refs/remotes/origin/HEAD\n\nAnd it would allow more exotic things, too, like:\n\n  # always update the remote notion of HEAD on every fetch\n  git config --add remote.origin.fetch ~HEAD:refs/remotes/origin/HEAD\n\n  # update a non-HEAD symref we track for our own purposes\n  git fetch origin ~refs/tags/LATEST:refs/tags/LATEST\n\n  # or the same thing but using the usual refspec \"dst defaults to src\"\n  # rule and dwim lookup magic\n  git fetch origin ~LATEST\n\nIn protocol v0 we don't get symref reports from the other side over the\ngit protocol (except for HEAD), but we could use the same logic we use\nfor determining HEAD for older versions of Git: find a ref that points\nto the same tip. Though I would say that unlike the existing code in\nguess_remote_head(), we'd probably want to treat an ambiguity as an\nerror, and not just default to refs/heads/master.\n\n-Peff\n"},{"id":"355632","messageId":"87a7pohadr.fsf@evledraar.gmail.com","threadId":"49126","inReplyTo":"CAP8UFD0_jpKdcDvNx5CYnmyDMagE_O-E7cef5VthaT_w-=4xsA@mail.gmail.com","subject":"Re: Syncing HEAD","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2018-08-14T22:05:36Z","receivedAt":"2018-08-14T22:05:41Z","isPatch":false,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Tue, Aug 14 2018, Christian Couder wrote:\n\n> Hi,\n>\n> When cloning with --mirror, the clone gets its HEAD initialized with\n> the value HEAD has in its origin remote. After that if HEAD changes in\n> origin there is no simple way to sync HEAD at the same time as the\n> refs are synced.\n>\n> It looks like the simplest way to sync HEAD is:\n>\n> 1) git remote show origin\n> 2) parse \"HEAD branch: XXX\" from the output of the above command\n> 3) git symbolic-ref HEAD refs/heads/XXX\n>\n> It looks like it would be quite easy to add an option to `fetch` to\n> sync HEAD at the same time as regular refs are synced because every\n> fetch from an origin that uses a recent Git contains something like:\n>\n> 19:55:39.304976 pkt-line.c:80           packet:          git< YYYYYYYY\n> HEAD\\0multi_ack thin-pack side-band side-band-64k ofs-delta shallow\n> deepen-since deepen-not deepen-relative no-progress include-tag\n> multi_ack_detailed no-done symref=HEAD:refs/heads/test-1\n> agent=git/2.18.0\n>\n> which in this example shows that HEAD is a symref to refs/heads/test-1\n> in origin.\n>\n> Is there a reason why no such option already exists? Would it makes\n> sense to add one? Is there any reason why it's not a good idea? Or am\n> I missing something?\n>\n> I am asking because GitLab uses HEAD in the bare repos it manages to\n> store the default branch against which the Merge Requests (same thing\n> as Pull Requests on GitHub) are created.\n>\n> So when people want to keep 2 GitLab hosted repos in sync, GitLab\n> needs to sync HEADs too, not just the refs.\n>\n> I think this could be useful to other setups than GitLab though.\n>\n> Thanks,\n> Christian.\n\nIsn't this some other facet of (or the same) bug I reported in\nhttps://public-inbox.org/git/87bmcyfh67.fsf@evledraar.gmail.com/ ?\n"},{"id":"355671","messageId":"CAP8UFD3S5vgMSuXfj1z0F7f-9SLVEm6boCHwdNwn7ysvXSRMrA@mail.gmail.com","threadId":"49126","inReplyTo":"20180814214723.GA667@sigill.intra.peff.net","subject":"Re: Syncing HEAD","fromName":"Christian Couder","fromEmail":"christian.couder@gmail.com","sentAt":"2018-08-15T05:49:25Z","receivedAt":"2018-08-15T05:49:28Z","isPatch":false,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"On Tue, Aug 14, 2018 at 11:47 PM, Jeff King <peff@peff.net> wrote:\n> On Tue, Aug 14, 2018 at 05:06:16PM -0400, Jeff King wrote:\n>\n>> On Tue, Aug 14, 2018 at 10:09:37PM +0200, Christian Couder wrote:\n>>\n>> > When cloning with --mirror, the clone gets its HEAD initialized with\n>> > the value HEAD has in its origin remote. After that if HEAD changes in\n>> > origin there is no simple way to sync HEAD at the same time as the\n>> > refs are synced.\n>> >\n>> > It looks like the simplest way to sync HEAD is:\n>> >\n>> > 1) git remote show origin\n>> > 2) parse \"HEAD branch: XXX\" from the output of the above command\n>> > 3) git symbolic-ref HEAD refs/heads/XXX\n>>\n>> How about:\n>>\n>>   git remote set-head origin -a\n>>\n>> ?\n>\n> Reading your message again, I see you actually care less about the\n> refs/remote placeholder and more about the actual HEAD in a bare repo.\n\nYeah, I am interesting in updating the actual HEAD in a bare repo.\n\n> In which case \"git remote\" isn't going to help, though its underlying\n> code has the algorithm you would want.\n\nOk, I will take a look at the algorithm.\n\n>> One tricky thing is that the name \"refs/remotes/<remote>/HEAD\" is only\n>> special by convention, and that convention is known on the writing side\n>> only by git-clone and git-remote. So obviously:\n>\n> And so here the convention is simpler, because we're talking about the\n> main HEAD. But we still have know if you want to do that, and not update\n> some refs/remotes/ symref in a bare repo.\n\nWe could maybe look at the \"remote.XXX.mirror\" config option. If it is\nset to \"true\", we could interpret that as meaning we are interested in\nupdating the main HEAD and not some refs/remotes/ symref.\n\n> So all of this really implies to me that you want to be able to say\n> \"take this symref on the other side and update this one on the local\n> side\". I.e., some way to tell a refspec \"don't update the value, update\n> the symref destination\". So imagine we made \"~\" the magic character for\n> \"just the symrefs\" (I picked that because it's not allowed in a\n> refname).\n>\n> Then you could do what you want with:\n>\n>   git config --add remote.origin.fetch ~HEAD:HEAD\n>\n> and these two would be the same:\n>\n>   git remote set-head origin -a\n>   git fetch origin ~HEAD:refs/remotes/origin/HEAD\n>\n> And it would allow more exotic things, too, like:\n>\n>   # always update the remote notion of HEAD on every fetch\n>   git config --add remote.origin.fetch ~HEAD:refs/remotes/origin/HEAD\n>\n>   # update a non-HEAD symref we track for our own purposes\n>   git fetch origin ~refs/tags/LATEST:refs/tags/LATEST\n>\n>   # or the same thing but using the usual refspec \"dst defaults to src\"\n>   # rule and dwim lookup magic\n>   git fetch origin ~LATEST\n\nAnd `git fetch origin ~HEAD` would sync the main HEAD?\n\nYeah, that looks like an interesting solution to the problem.\n\nI wonder though if we should restrict the way `git fetch origin ~XXX`\nsearches the .git/ directory itself.\n\n> In protocol v0 we don't get symref reports from the other side over the\n> git protocol (except for HEAD), but we could use the same logic we use\n> for determining HEAD for older versions of Git: find a ref that points\n> to the same tip. Though I would say that unlike the existing code in\n> guess_remote_head(), we'd probably want to treat an ambiguity as an\n> error, and not just default to refs/heads/master.\n\nI wonder what `git fetch origin ~refs/heads/*:refs/heads/*` should do.\nCould it know which refs are symrefs using protocol v0? Should it\nguess that refs with uppercase names are symrefs? Should we allow '*'\nat all in those kinds of refspecs?\n\nIt looks like making \"~\" the magic character for \"just the symrefs\"\nmight be a good solution in the end, though we might want to restrict\nit to protocol v2.\nSo perhaps something like `git fetch --update-head` that you suggest\nin another email would be a good solution for now and for protocol v0.\n"},{"id":"355890","messageId":"20180817014757.GA17048@sigill.intra.peff.net","threadId":"49126","inReplyTo":"CAP8UFD3S5vgMSuXfj1z0F7f-9SLVEm6boCHwdNwn7ysvXSRMrA@mail.gmail.com","subject":"Re: Syncing HEAD","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2018-08-17T01:47:58Z","receivedAt":"2018-08-17T01:48:01Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Aug 15, 2018 at 07:49:25AM +0200, Christian Couder wrote:\n\n> > And so here the convention is simpler, because we're talking about the\n> > main HEAD. But we still have know if you want to do that, and not update\n> > some refs/remotes/ symref in a bare repo.\n> \n> We could maybe look at the \"remote.XXX.mirror\" config option. If it is\n> set to \"true\", we could interpret that as meaning we are interested in\n> updating the main HEAD and not some refs/remotes/ symref.\n\nYeah, for the mirror case I think that would be sufficient, and that's a\nsubset of the larger problem. I'm not _totally_ opposed to solving just\nthis narrow case, but I think it would be great if we could solve the\nlarger problem.\n\n> >   # or the same thing but using the usual refspec \"dst defaults to src\"\n> >   # rule and dwim lookup magic\n> >   git fetch origin ~LATEST\n> \n> And `git fetch origin ~HEAD` would sync the main HEAD?\n\nYes, exactly.\n\n> I wonder though if we should restrict the way `git fetch origin ~XXX`\n> searches the .git/ directory itself.\n\nThe matching is done against the list of refs that the remote\nadvertises. So everything is under refs/ except for HEAD. If you tried\nto do something funky with top-level refs like:\n\n  git fetch origin ~MERGE_HEAD\n\nit would always come up with \"couldn't find remote ref MERGE_HEAD\".\n\n> I wonder what `git fetch origin ~refs/heads/*:refs/heads/*` should do.\n> Could it know which refs are symrefs using protocol v0? Should it\n> guess that refs with uppercase names are symrefs? Should we allow '*'\n> at all in those kinds of refspecs?\n\nThat's an interesting question. I'd be tempted to say that it is an\nerror to use \"~\" with a wildcard ref, at least for the first version of\nthe patch. That way we don't back ourselves into a corner, and can make\nit do something useful later.\n\nI think one sane set of rules is:\n\n - for protocol v2+, where we know which remote refs are symrefs,\n   transfer them as symrefs\n\n - for protocol v0, either transfer them as normal refs (except HEAD,\n   which we always suspect of being a symref), or simply declare it\n   an error\n\nFor the most part, though, I think people would be fine without\ncombining wildcards with the symref feature, and would just do:\n\n  +refs/*:refs/*\n  ~HEAD:HEAD\n\nfor a bare mirror, and:\n\n  +refs/heads/*:refs/remotes/origin/*\n  ~HEAD:refs/remotes/origin/HEAD\n\nfor an auto-updating non-bare remote.\n\n> It looks like making \"~\" the magic character for \"just the symrefs\"\n> might be a good solution in the end, though we might want to restrict\n> it to protocol v2.\n> So perhaps something like `git fetch --update-head` that you suggest\n> in another email would be a good solution for now and for protocol v0.\n\nYou still have the problem with --update-head of where to store the\nresult. I think the semantics for a non-wildcard \"~\" are clear enough,\neven with protocol v0, that it would be OK to start down that road.\n\nA few final thoughts:\n\n - I like the look of \"~\", but there are not very many characters\n   disallowed in refs, and we're using one of them. Another notable one\n   is \"^\", from which we've built the \"^{foo}\" syntax elsewhere. So this\n   could be something like \"^{symref}HEAD:HEAD\", which leaves room for\n   new \"^{}\" types in the future. But man, that looks really ugly\n   compared to \"~HEAD:HEAD\".\n\n - Is there a case for a symref update where we'd want to require a\n   force-push? Maybe if the local side exists and is not already a\n   symref?\n\n - What do we do if the other side isn't a symref (e.g., a detached\n   HEAD)? Is that an error? Do we detach ourselves? Does it require a\n   force?\n\n-Peff\n"},{"id":"355918","messageId":"xmqq6009c5ys.fsf@gitster-ct.c.googlers.com","threadId":"49126","inReplyTo":"20180814214723.GA667@sigill.intra.peff.net","subject":"Re: Syncing HEAD","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-08-17T16:28:59Z","receivedAt":"2018-08-17T16:29:04Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> So all of this really implies to me that you want to be able to say\n> \"take this symref on the other side and update this one on the local\n> side\". I.e., some way to tell a refspec \"don't update the value, update\n> the symref destination\". ...\n> ...\n>   git fetch origin ~HEAD:refs/remotes/origin/HEAD\n\nWe need to be a bit careful here.\n\nYou can define the meaning of the above sanely if you know that\nrefmap refs/heads/*:refs/remotes/origin/* is in effect for the\nremote to read \"My HEAD points at refs/heads/frotz\" and interpret it\nas \"In order to match, I need to make my refs/remotes/origin/HEAD to\npoint at refs/remotes/origin/frotz\".\n\nAlso, what should the above form of \"git fetch\" write in FETCH_HEAD?\nShould \"git pull origin ~HEAD:refs/remotes/origin/HEAD\" run the fetch\nand then merge it (which may have value of refs/remotes/origin/frotz)\nto the current branch?  Should the underlying fetch be also fetching\nthe frotz branch from them at the same time, or do we attempt to merge\na possibly stale 'frotz' (which might not even have been there, the\nlast time we fetched from them)?\n\n"},{"id":"355920","messageId":"20180817164850.GA7789@sigill.intra.peff.net","threadId":"49126","inReplyTo":"xmqq6009c5ys.fsf@gitster-ct.c.googlers.com","subject":"Re: Syncing HEAD","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2018-08-17T16:48:50Z","receivedAt":"2018-08-17T16:48:53Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Aug 17, 2018 at 09:28:59AM -0700, Junio C Hamano wrote:\n\n> Jeff King <peff@peff.net> writes:\n> \n> > So all of this really implies to me that you want to be able to say\n> > \"take this symref on the other side and update this one on the local\n> > side\". I.e., some way to tell a refspec \"don't update the value, update\n> > the symref destination\". ...\n> > ...\n> >   git fetch origin ~HEAD:refs/remotes/origin/HEAD\n> \n> We need to be a bit careful here.\n> \n> You can define the meaning of the above sanely if you know that\n> refmap refs/heads/*:refs/remotes/origin/* is in effect for the\n> remote to read \"My HEAD points at refs/heads/frotz\" and interpret it\n> as \"In order to match, I need to make my refs/remotes/origin/HEAD to\n> point at refs/remotes/origin/frotz\".\n\nGood point. I was thinking too much about the symlink itself and not its\ndestination. You need some way of mapping that destination, as well.\n\nFor Christian's case, it is really the \"refs/*:refs/*\" mapping that he\nwould want to emulate (because he'd be doing ~HEAD:HEAD). In some cases,\nlike that one, you could infer the mapping from the HEAD:HEAD itself (X\non the remote becomes X locally). But that does not work for the\nrefs/remotes case. You might infer from \"~HEAD:refs/remotes/origin/HEAD\"\nthat \"X becomes refs/remotes/origin/X\", but it is actually \"refs/heads/X\nbecomes ...\".\n\nSo yeah, this really does need pairing with the overall ref mapping.\n\nI think that's doable even for the example I gave above, because we\ncould find those refspecs in the config. But:\n\n  git fetch git://... ~HEAD:HEAD\n\ndoes not have that information. We may or may not have fetched the\npointed-to ref previously.\n\nWhat if this _required_ that the symref destination from the other side\nalso be something that we are fetching, and was otherwise an error? That\nwould avoid any config trickery. It does mean that \"git fetch origin\n~HEAD:HEAD\" does not work.  But I think you'd generally want to pair it\nwith a fetch anyway. I.e., Either two configured refspecs, or if a\none-off fetch from a URL, fetching the branches and the symref at the\nsame time.\n\nI suppose the one case it would not support is \"I want to fetch HEAD as\na symref and whatever branch it points to, but I do not yet know what\nthat branch is\". Or, I suppose, \"I do not want to update any branches,\nbut just update my notion of HEAD\" (i.e., what \"remote set-head -a\"\ncurrently does).\n\n> Also, what should the above form of \"git fetch\" write in FETCH_HEAD?\n> Should \"git pull origin ~HEAD:refs/remotes/origin/HEAD\" run the fetch\n> and then merge it (which may have value of refs/remotes/origin/frotz)\n> to the current branch?  Should the underlying fetch be also fetching\n> the frotz branch from them at the same time, or do we attempt to merge\n> a possibly stale 'frotz' (which might not even have been there, the\n> last time we fetched from them)?\n\nI'd be tempted to say that a symref fetch writes nothing into FETCH_HEAD\nat all. Which would make a bare \"git pull origin ~HEAD\" an error. I'm\nsure there are cases it _could_ do something useful, but there are so\nmany where it doesn't make sense.\n\n-Peff\n"}]}