{"thread":{"id":"32436","subject":"Pushing symbolic references to remote repositories?","startedAt":"2012-12-21T19:53:15Z","lastAt":"2012-12-23T01:10:59Z","messageCount":6,"participants":["Dun Peal","Shawn Pearce","Junio C Hamano","Andreas Schwab","Sitaram Chamarty"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"205370","messageId":"CAD03jn5ACZyxJM9LEOSJov3BsT3W1N0sV3WYwcerJciMSpmSPA@mail.gmail.com","threadId":"32436","inReplyTo":null,"subject":"Pushing symbolic references to remote repositories?","fromName":"Dun Peal","fromEmail":"dunpealer@gmail.com","sentAt":"2012-12-21T19:53:15Z","receivedAt":"2012-12-21T19:53:15Z","isPatch":false,"sender":{"key":"dunpealer@gmail.com","avatar":"https://gravatar.com/avatar/42f3e6a1166eb44e33f24c20ccbe809fa8591413f366dfe3755c8a8d4935ace9?d=mp&s=160"},"body":"Hi,\n\nI need to share a symbolic reference - essentially, a named pointer to\nanother reference - among multiple repositories.\n\nAs shown in the code below, I can successfully create a local\nsymbolic-ref `foo_ptr` to branch `foo`, but can't push it to a remote,\nin this case `origin`:\n\n$ git branch foo; git symbolic-ref foo_ptr refs/heads/foo; git rev-parse foo_ptr\nfbfec27dc6d42d48ca5d5b178caa34c666a4c39b\n$ git push origin foo foo_ptr\nerror: dst ref refs/heads/foo receives from more than one src.\n\nIs there a clean and reliable way to do that, or are symbolic\nreferences just not meant to be shared?\n\nThanks, D.\n"},{"id":"205376","messageId":"CAJo=hJvqptfKqM+6J8Ddfb5qcqjAU8bB_JO9VB-XVsCCf64NUQ@mail.gmail.com","threadId":"32436","inReplyTo":"CAD03jn5ACZyxJM9LEOSJov3BsT3W1N0sV3WYwcerJciMSpmSPA@mail.gmail.com","subject":"Re: Pushing symbolic references to remote repositories?","fromName":"Shawn Pearce","fromEmail":"spearce@spearce.org","sentAt":"2012-12-21T21:54:29Z","receivedAt":"2012-12-21T21:54:29Z","isPatch":false,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"On Fri, Dec 21, 2012 at 11:53 AM, Dun Peal <dunpealer@gmail.com> wrote:\n> I need to share a symbolic reference - essentially, a named pointer to\n> another reference - among multiple repositories.\n>\n> As shown in the code below, I can successfully create a local\n> symbolic-ref `foo_ptr` to branch `foo`, but can't push it to a remote,\n> in this case `origin`:\n>\n> $ git branch foo; git symbolic-ref foo_ptr refs/heads/foo; git rev-parse foo_ptr\n> fbfec27dc6d42d48ca5d5b178caa34c666a4c39b\n> $ git push origin foo foo_ptr\n> error: dst ref refs/heads/foo receives from more than one src.\n>\n> Is there a clean and reliable way to do that, or are symbolic\n> references just not meant to be shared?\n\nThere is no support for symbolic references in the network protocol,\nso they cannot currently be shared by git push or git fetch.\n"},{"id":"205382","messageId":"7vip7vrof6.fsf@alter.siamese.dyndns.org","threadId":"32436","inReplyTo":"CAJo=hJvqptfKqM+6J8Ddfb5qcqjAU8bB_JO9VB-XVsCCf64NUQ@mail.gmail.com","subject":"Re: Pushing symbolic references to remote repositories?","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-12-21T23:11:25Z","receivedAt":"2012-12-21T23:11:25Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Shawn Pearce <spearce@spearce.org> writes:\n\n> On Fri, Dec 21, 2012 at 11:53 AM, Dun Peal <dunpealer@gmail.com> wrote:\n>>\n>> Is there a clean and reliable way to do that, or are symbolic\n>> references just not meant to be shared?\n>\n> There is no support for symbolic references in the network protocol,\n> so they cannot currently be shared by git push or git fetch.\n\nWhat Shawn said is technically correct, but do not read it as \"we\nknow what protocol update we want at the network level, but we\nhaven't got around implementing it\".\n\nIt is unclear what it means to send symrefs across repositories\n(rather, what we want it to mean).  In that sense, the reality is\ncloser to the latter of your choices.\n\nThere are three primary kinds of symrefs to consider:\n\n * worktree/.git/HEAD is meant to point at the branch that is\n   currently checked out.  This is designed to be under sole control\n   of the person who is working in such a repository and the outside\n   people have no business knowing which branch he happens to be\n   working on at this very moment (it can change the next minute).\n\n * worktree/.git/refs/remotes/$name/HEAD is meant to point at the\n   remote-tracking branch of the named remote (e.g. 'origin') the\n   local user is interested in, to let \"git checkout -b topic\n   origin\" work, instead of a longer \"git checkout -b topic\n   origin/master\".\n\n * bare.git/HEAD is meant to point at the \"primary\" branch at a\n   bare, distribution repository nobody works in directly.  The\n   branch pointed at by the symref rarely, if ever, changes.\n\nNobody will imagine flipping worktree/.git/HEAD from outside by\npushing into it (unless you are trying to pull a prank on the user\nwho is working in that repository).  Also, nobody would want to\nupdate this symref by fetching from outside.  So we won't have to\nconsider updating the first kind in the following discussion.\n\nIt is unlikely that anybody sane wants to update the remote-tracking\nworktree/.git/refs/remotes/origin/HEAD from outside by pushing.\n\nIt *may* make sense to update it upon fetching, though, in some\ncases.  You first clone from bare.git/HEAD and learn [*1*] that the\nprimary branch at the time of cloning was 'master', and\nremote/origin/HEAD in your repository is set to point at\norigin/master.  Now the upstream designates a different branch as\nthe primary (perhaps 'trunk'), and you may want your next \"git\nfetch\" to repoint your remote/origin/HEAD to point at\n'remote/origin/trunk'.\n\nHowever, even this one is not unconditionally a good idea.  The\nbranch you are interested in might be different from what your\nremote designates as its primary branch in the first place.  You may\nfor example want to follow along 'next' after cloning from me.  E.g.\n\n    $ git clone     git://git.kernel.org/pub/scm/git/git.git git\n    $ cd git\n    $ git symbolic-ref refs/remotes/origin/HEAD\n    refs/remotes/origin/next\n\nIt is not clear if it is a good idea to allow \"git fetch\" to repoint\nyour remotes/origin/HEAD to whatever I chose to point my HEAD at.\n\nSo for the second kind, pushing is irrelevant, and fetching is\n\"perhaps sometimes it may make sense\".\n\nI think that the only one and a half sensible use cases that\nunconditionally make sense to update symrefs across repositories are\nto update bare.git/HEAD symref:\n\n - update bare.git/HEAD of a repository that is a local mirror of a\n   more authoritative repository with \"git fetch --mirror\", in which\n   case you do want to follow what branch is designated as the\n   primary by the project you are mirroring from;\n\n - update bare.git/HEAD from outside by some means to change which\n   branch is the primary one for the project. Only because your\n   hosting site does not give you an easy way to do so, pushing from\n   another repository that happens to point its HEAD at a different\n   branch seems to be one plausible way to do so, but that does not\n   have to be the only way.\n\n\n[Footnote]\n\n*1* We would need to update the network protocol for this purpose,\nas most transports do not carry this information and clone has to\nguess which branch bare.git/HEAD points at.\n\nThe purpose of this message, though, is to illustrate that the\nprotocol update to carry the information is not the end of the\nstory, but merely is an enabling beginning. We need to know what\nsemantics we would want to implement on top of that transfer.\n"},{"id":"205406","messageId":"m2ehiiv3nb.fsf@linux-m68k.org","threadId":"32436","inReplyTo":"7vip7vrof6.fsf@alter.siamese.dyndns.org","subject":"Re: Pushing symbolic references to remote repositories?","fromName":"Andreas Schwab","fromEmail":"schwab@linux-m68k.org","sentAt":"2012-12-22T09:26:32Z","receivedAt":"2012-12-22T09:26:32Z","isPatch":false,"sender":{"key":"schwab@linux-m68k.org","avatar":"https://avatars.githubusercontent.com/u/2175493?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> I think that the only one and a half sensible use cases that\n> unconditionally make sense to update symrefs across repositories are\n> to update bare.git/HEAD symref:\n>\n>  - update bare.git/HEAD of a repository that is a local mirror of a\n>    more authoritative repository with \"git fetch --mirror\", in which\n>    case you do want to follow what branch is designated as the\n>    primary by the project you are mirroring from;\n>\n>  - update bare.git/HEAD from outside by some means to change which\n>    branch is the primary one for the project. Only because your\n>    hosting site does not give you an easy way to do so, pushing from\n>    another repository that happens to point its HEAD at a different\n>    branch seems to be one plausible way to do so, but that does not\n>    have to be the only way.\n\nThis is not limited to HEAD, any ref may want to be set up as a symref\nat a remote repo.  For example, I want to set up a symref master ->\ntrunk at a repository I have no shell access to.  Without this I get\nspurious error whenever I fetch from that remote (where master and trunk\nare separate refs) into a local mirror which does have the symref:\n\n>From git://repo.or.cz/emacs\n   f0ae89f..5595931  master     -> master\nerror: Ref refs/heads/trunk is at 559593152b9de5a1c144729e0583fa7968abab22 but expected f0ae89f92326beb3f5a19e90c8f4fe0ab6197926\n ! f0ae89f..5595931  trunk      -> trunk  (unable to update local ref)\n\nAndreas.\n\n-- \nAndreas Schwab, schwab@linux-m68k.org\nGPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5\n\"And now for something completely different.\"\n"},{"id":"205425","messageId":"7vy5gqq6w8.fsf@alter.siamese.dyndns.org","threadId":"32436","inReplyTo":"m2ehiiv3nb.fsf@linux-m68k.org","subject":"Re: Pushing symbolic references to remote repositories?","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-12-22T18:27:35Z","receivedAt":"2012-12-22T18:27:35Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Andreas Schwab <schwab@linux-m68k.org> writes:\n\n> This is not limited to HEAD, any ref may want to be set up as a symref\n> at a remote repo.  For example, I want to set up a symref master ->\n> trunk at a repository I have no shell access to.\n\nThat is exactly the \"hosting side does not give you an easy way so\npushing seems to be one plausible but not necessarily has to be the\nonly way\" case, so it is already covered in the discussion.\n"},{"id":"205437","messageId":"CAMK1S_iKYb0sK+2+H1b7wAPjJGEhJHJk9eK1bsMqxOGKoJuipg@mail.gmail.com","threadId":"32436","inReplyTo":"7vy5gqq6w8.fsf@alter.siamese.dyndns.org","subject":"Re: Pushing symbolic references to remote repositories?","fromName":"Sitaram Chamarty","fromEmail":"sitaramc@gmail.com","sentAt":"2012-12-23T01:10:59Z","receivedAt":"2012-12-23T01:10:59Z","isPatch":false,"sender":{"key":"sitaramc@gmail.com","avatar":"https://avatars.githubusercontent.com/u/43316?v=4"},"body":"On Sat, Dec 22, 2012 at 11:57 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Andreas Schwab <schwab@linux-m68k.org> writes:\n>\n>> This is not limited to HEAD, any ref may want to be set up as a symref\n>> at a remote repo.  For example, I want to set up a symref master ->\n>> trunk at a repository I have no shell access to.\n>\n> That is exactly the \"hosting side does not give you an easy way so\n> pushing seems to be one plausible but not necessarily has to be the\n> only way\" case, so it is already covered in the discussion.\n\nJust a minor FYI (and at the risk of tooting my own horn) but if the\nhosting side is gitolite, you can.set it up so that any user with\nwrite permissions to the repo can run 'git symbolic-ref' with\narbitrary arguments even though he does not get a shell.\n\nThe \"-m <reason>\" has some constraints because gitolite does not allow\na lot of characters in arguments to remote commands but that's mostly\nuseless unless you have core.logAllRefUpdates set anyway.\n"}]}