{"thread":{"id":"17841","subject":"FETCH_HEAD question","startedAt":"2009-02-17T04:43:32Z","lastAt":"2009-02-18T00:30:00Z","messageCount":15,"participants":["Jay Soffian","Junio C Hamano","Sitaram Chamarty","Johannes Schindelin"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"105071","messageId":"76718490902162043k78e615b5g7ba4b7ac95e73b18@mail.gmail.com","threadId":"17841","inReplyTo":null,"subject":"FETCH_HEAD question","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2009-02-17T04:43:32Z","receivedAt":"2009-02-17T04:43:32Z","isPatch":false,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"I did this the other day out of mild curiosity:\n\n$ git fetch\n$ git merge FETCH_HEAD\n\nWhich did something, but not something that was at all useful. It\nmerges in the first ref listed in FETCH_HEAD. It does not appear to be\nan accident that it does this, as git merge has special treatment for\nFETCH_HEAD to generate the merge message.\n\nWhy does this behavior exist? Historical?\n\nj.\n"},{"id":"105073","messageId":"76718490902162111o373065bwb74a187b016beb0a@mail.gmail.com","threadId":"17841","inReplyTo":"76718490902162043k78e615b5g7ba4b7ac95e73b18@mail.gmail.com","subject":"Re: FETCH_HEAD question","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2009-02-17T05:11:04Z","receivedAt":"2009-02-17T05:11:04Z","isPatch":false,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"On Mon, Feb 16, 2009 at 11:43 PM, Jay Soffian <jaysoffian@gmail.com> wrote:\n> I did this the other day out of mild curiosity:\n>\n> $ git fetch\n> $ git merge FETCH_HEAD\n>\n> Which did something, but not something that was at all useful. It\n> merges in the first ref listed in FETCH_HEAD. It does not appear to be\n> an accident that it does this, as git merge has special treatment for\n> FETCH_HEAD to generate the merge message.\n>\n> Why does this behavior exist? Historical?\n\nTo be clear, this seems only to be useful if you are only fetching a\nsingle branch from remote. Otherwise the branch which you end up\nmerging (the first alphabetically) may very well not be what the\ncurrent checked-out branch is based on.\n\nSo to work correctly in the case of pulling multiple branches,\ndwim_ref() would have to return the sha1 corresponding to the single\nline in FETCH_HEAD that is not marked \"not-for-merge\" and git merge\nwould similarly need to use that line for the merge message. Or git\nfetch would need to place the non-not-for-merge ref first in the file.\n\nI found this in the archives, but it didn't really answer my question\nabout why it got implemented the current way:\n\nhttp://thread.gmane.org/gmane.comp.version-control.git/42788/focus=42850\n\nj.\n"},{"id":"105074","messageId":"7veixxaale.fsf@gitster.siamese.dyndns.org","threadId":"17841","inReplyTo":"76718490902162043k78e615b5g7ba4b7ac95e73b18@mail.gmail.com","subject":"Re: FETCH_HEAD question","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-02-17T05:36:29Z","receivedAt":"2009-02-17T05:36:29Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jay Soffian <jaysoffian@gmail.com> writes:\n\n> I did this the other day out of mild curiosity:\n>\n> $ git fetch\n> $ git merge FETCH_HEAD\n>\n> Which did something, but not something that was at all useful. It\n> merges in the first ref listed in FETCH_HEAD. It does not appear to be\n> an accident that it does this, as git merge has special treatment for\n> FETCH_HEAD to generate the merge message.\n\n\"git pull\" internally invokes \"git fetch\" to learn the tips of branches\nthe invoking user is interested in.  \"git fetch\" downloads the necessary\nobjects to complete the ancestry chain from local refs to these tips of\nbranches, and then uses FETCH_HEAD to communicate which commit object\nthese branches point at, and at the same time which lines in the file\ndescribe the commits that need to be merged into the current HEAD by\nmarking lines with not-for-merge markers (\"cat .git/FETCH_HEAD\" to see how\nit is done), back to the invoking \"git pull\".  \"git pull\" then inspects\nthis file to decide which commit object to pass to \"git merge\".\n\nThis division of labor makes sense because \"git fetch\" knows more about\nthe user preference (\"remotes.*.fetch\" and \"branch.*.merge\" configuration\nitems, .git/remotes/* files, and .git/branches/* files are inspected by\nthe command).  \n\nThe rule initially was that the first non-wildcard Pull: rule in remotes/*\nfile specifies the commits to be merged or something, and over time, the\nsystem learned the more elaborate per-branch settings via branch.*.merge\nvariables, but the idea has always been that you cannot just grab the\nfirst line of FETCH_HEAD and expect that is what you want to merge.  At\nleast you need to omit the ones that are marked not-for-merge (see how it\nis done by \"git-pull.sh\" with a simple sed script), even though\n\"FETCH_HEAD\" can be used as an extended SHA-1 to name the commit object\nrecorded on the first line in the file.\n\nHaving said that, being able to directly use FETCH_HEAD as an extended\nSHA-1 is often useful when somebody asks an integrator to pull one-shot\nwith git-request-pull.  Upon receiving such a request, the integrator can\nsay:\n\n\t$ git fetch git://repo.or.cz/his.git for-linus\n        $ git log -p ..FETCH_HEAD ;# to inspect\n        $ git merge FETCH_HEAD\n\nto take advantage of the fact that the commit object name that appears at\nthe beginning of resulting FETCH_HEAD file is actually the commit we would\nwant, because by definition FETCH_HEAD records only one commit when we are\nfetching only one branch.\n\nIncidentally, such a command line to explicitly fetch one single branch is\ninterpreted by \"git fetch\" to mean that you are interested in merging the\ntip of the fetched branch, and the first line of the resulting FETCH_HEAD\nfile is not marked with not-for-merge.  Therefore,\n\n\t$ git pull git://repo.or.cz/his.git for-linus\n\nwould also work regardless of what you have in .git/config file.\n"},{"id":"105080","messageId":"76718490902162221i31e02052j48c9f620a2d47985@mail.gmail.com","threadId":"17841","inReplyTo":"7veixxaale.fsf@gitster.siamese.dyndns.org","subject":"Re: FETCH_HEAD question","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2009-02-17T06:21:00Z","receivedAt":"2009-02-17T06:21:00Z","isPatch":false,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"On Tue, Feb 17, 2009 at 12:36 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> [... explanation of how git pull and git fetch communicate via FETCH_HEAD...]\n\nI'm aware of all that, and I apologize for not making that clear,\nsince I made you do lots of extra typing. :-(\n\n> Having said that, being able to directly use FETCH_HEAD as an extended\n> SHA-1 is often useful when somebody asks an integrator to pull one-shot\n> with git-request-pull.  Upon receiving such a request, the integrator can\n> say:\n>\n>        $ git fetch git://repo.or.cz/his.git for-linus\n>        $ git log -p ..FETCH_HEAD ;# to inspect\n>        $ git merge FETCH_HEAD\n>\n> to take advantage of the fact that the commit object name that appears at\n> the beginning of resulting FETCH_HEAD file is actually the commit we would\n> want, because by definition FETCH_HEAD records only one commit when we are\n> fetching only one branch.\n\nThat makes sense, but I was confused why git merge goes through the\ntrouble of stripping out the not-for-merge tag which in the above use\ncase wouldn't be there.\n\nj.\n"},{"id":"105084","messageId":"7vr61x8ra4.fsf@gitster.siamese.dyndns.org","threadId":"17841","inReplyTo":"76718490902162221i31e02052j48c9f620a2d47985@mail.gmail.com","subject":"Re: FETCH_HEAD question","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-02-17T07:18:59Z","receivedAt":"2009-02-17T07:18:59Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jay Soffian <jaysoffian@gmail.com> writes:\n\n> On Tue, Feb 17, 2009 at 12:36 AM, Junio C Hamano <gitster@pobox.com> wrote:\n>> [... explanation of how git pull and git fetch communicate via FETCH_HEAD...]\n>\n> I'm aware of all that, and I apologize for not making that clear,\n> since I made you do lots of extra typing. :-(\n\nYour \"git merge FETCH_HEAD\" after fetching random set of refs by the\ndefault wildcard refspec in .git/config made me suspect you aren't.\n\n>>        $ git fetch git://repo.or.cz/his.git for-linus\n>>        $ git log -p ..FETCH_HEAD ;# to inspect\n>>        $ git merge FETCH_HEAD\n>> ...\n> That makes sense, but I was confused why git merge goes through the\n> trouble of stripping out the not-for-merge tag which in the above use\n> case wouldn't be there.\n\nBecause it is designed to handle a lot more general case of fetching all\nremote branches into your remote tracking branches with wildcard refspecs,\nand most of the entries need to be marked with not-for-merge marker.  If\nyou left only the for-merge branches, you would not have any sane way to\nlearn what refs were fetched after you said \"git fetch\" (and no, looking\nat timestamp of files in .git/refs/remotes/origin/ is not a sensible\nanswer).\n"},{"id":"105088","messageId":"76718490902162341y2f122427i470c77d3915ff554@mail.gmail.com","threadId":"17841","inReplyTo":"7vr61x8ra4.fsf@gitster.siamese.dyndns.org","subject":"Re: FETCH_HEAD question","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2009-02-17T07:41:15Z","receivedAt":"2009-02-17T07:41:15Z","isPatch":false,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"On Tue, Feb 17, 2009 at 2:18 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> Because it is designed to handle a lot more general case of fetching all\n> remote branches into your remote tracking branches with wildcard refspecs,\n> and most of the entries need to be marked with not-for-merge marker.  If\n> you left only the for-merge branches, you would not have any sane way to\n> learn what refs were fetched after you said \"git fetch\" (and no, looking\n> at timestamp of files in .git/refs/remotes/origin/ is not a sensible\n> answer).\n\nWe are talking past each other.\n\nI understand the not-for-merge marker, why git fetch puts it there,\nand how it is used by git pull.\n\nI was asking why \"git merge FETCH_HEAD\" is useful, and you gave an\nexample of fetching a *single* branch using \"git fetch <url>\n<branch>\". But in that case, as you said, git fetch does *not* leave a\n\"not-for-merge\" marker, since only one branch was fetched.\n\nSo then, why does \"git merge FETCH_HEAD\" bother to strip out a\nnot-for-merge marker that wouldn't be there?\n\nI can only guess there is a use case where one fetches multiple\nbranches and then uses \"git merge FETCH_HEAD\".\n\nj.\n"},{"id":"105094","messageId":"slrngpkt3s.rl5.sitaramc@sitaramc.homelinux.net","threadId":"17841","inReplyTo":"76718490902162221i31e02052j48c9f620a2d47985@mail.gmail.com","subject":"Re: FETCH_HEAD question","fromName":"Sitaram Chamarty","fromEmail":"sitaramc@gmail.com","sentAt":"2009-02-17T08:25:32Z","receivedAt":"2009-02-17T08:25:32Z","isPatch":false,"sender":{"key":"sitaramc@gmail.com","avatar":"https://avatars.githubusercontent.com/u/43316?v=4"},"body":"On 2009-02-17, Jay Soffian <jaysoffian@gmail.com> wrote:\n> On Tue, Feb 17, 2009 at 12:36 AM, Junio C Hamano <gitster@pobox.com> wrote:\n>> [... explanation of how git pull and git fetch communicate via FETCH_HEAD...]\n>\n> I'm aware of all that, and I apologize for not making that clear,\n> since I made you do lots of extra typing. :-(\n\noy -- ease up on that apology; I'm thankful he did --\ncleared up a bunch of stuff for me!\n\nJunio: I hope you put it on your blog.  These detailed,\ndescriptive, explanations should all be in one place for\neasy reference.\n"},{"id":"105098","messageId":"7vy6w5795h.fsf@gitster.siamese.dyndns.org","threadId":"17841","inReplyTo":"76718490902162341y2f122427i470c77d3915ff554@mail.gmail.com","subject":"Re: FETCH_HEAD question","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-02-17T08:35:54Z","receivedAt":"2009-02-17T08:35:54Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jay Soffian <jaysoffian@gmail.com> writes:\n\n> So then, why does \"git merge FETCH_HEAD\" bother to strip out a\n> not-for-merge marker that wouldn't be there?\n\nIn general, FETCH_HEAD is usable as an extended SHA-1, in that any file\nthat is in .git/ and begins with [0-9a-f]{40} names that object.  That is\nhow \"git log -p ..FETCH_HEAD\" in my example worked.\n\nThe reason stripping of not-for-merge is done is to support a usage that\nis not so sane as well.\n\nYou can do a wildcard fetch that leaves full of not-for-merge entries in\nFETCH_HEAD, and then use FETCH_HEAD as an extended SHA-1 to merge the one\nthat happens to be on the first line.  \"git merge\" *could* in such a case\nproduce:\n\n\tMerge commit $ugly_40_hexadecimal_name\n\nto say that it merged that commit named by a random extended SHA-1, but it\nknows that FETCH_HEAD has better information than that.  The line tells\nwhere you got that commit from.  And that is recorded past not-for-merge\nmarker (if exists, otherwise it is an empty string) that is enclosed by a\nHT on each side.  This is a direct translation from the scripted version\nthat did:\n\n\tsed -e 's/\tnot-for-merge\t/\t\t/' -e 1q\n\nIt is being overly nice to produce a sensible merge message, even when you\nasked it to do something not very sensible.\n\nNow to something totally useless.\n\nAfter reading the builtin-merge.c and original git-merge.sh (now in\ncontrib/examples) script, I think it could have done something entirely\ndifferent.\n\nIt could have done this instead.\n\n\tsed -e '/\tnot-for-merge\t/d'\n\nto learn the commits and their human-readable origins, and it could have\ntried to reproduce what \"git pull\" did when it invoked git-merge using\nthat information.  Then you could use this workflow:\n\n\t$ git pull <possibly with arguments>\n        ... oops, conflicted and is very messy.\n        ... I tried to resolve, but failed and made the mess even worse.\n        ... Let's start over.\n        $ git reset --hard\n        ... FETCH_HEAD knows which refs are for merging\n        $ git merge FETCH_HEAD\n\nThat is, no matter what the arguments were for the initial \"git pull\",\nwhat should be merged is recorded in FETCH_HEAD, and that is how you can\nretry the merge without refetching over the network.\n\nBut such a change makes FETCH_HEAD different from what it traditionally\nmeant, and does that only to \"git merge\", making the result very\ninconsistent.  For example, \"git log ..FETCH_HEAD\" will still use the\nobject name on the first line, and it won't be a way to convince yourself\nthat the changes are sensible and it is Ok to run \"git merge FETCH_HEAD\"\nanymore.  So I do not think such a change will be an improvement.\n"},{"id":"105180","messageId":"76718490902170914p6258b77ak81318f13757f0dfd@mail.gmail.com","threadId":"17841","inReplyTo":"7vy6w5795h.fsf@gitster.siamese.dyndns.org","subject":"Re: FETCH_HEAD question","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2009-02-17T17:14:29Z","receivedAt":"2009-02-17T17:14:29Z","isPatch":false,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"On Tue, Feb 17, 2009 at 3:35 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> Now to something totally useless.\n>\n> After reading the builtin-merge.c and original git-merge.sh (now in\n> contrib/examples) script, I think it could have done something entirely\n> different.\n>\n> It could have done this instead.\n>\n>        sed -e '/       not-for-merge   /d'\n>\n> to learn the commits and their human-readable origins, and it could have\n> tried to reproduce what \"git pull\" did when it invoked git-merge using\n> that information.  Then you could use this workflow:\n>\n>        $ git pull <possibly with arguments>\n>        ... oops, conflicted and is very messy.\n>        ... I tried to resolve, but failed and made the mess even worse.\n>        ... Let's start over.\n>        $ git reset --hard\n>        ... FETCH_HEAD knows which refs are for merging\n>        $ git merge FETCH_HEAD\n>\n> That is, no matter what the arguments were for the initial \"git pull\",\n> what should be merged is recorded in FETCH_HEAD, and that is how you can\n> retry the merge without refetching over the network.\n>\n> But such a change makes FETCH_HEAD different from what it traditionally\n> meant, and does that only to \"git merge\", making the result very\n> inconsistent.  For example, \"git log ..FETCH_HEAD\" will still use the\n> object name on the first line, and it won't be a way to convince yourself\n> that the changes are sensible and it is Ok to run \"git merge FETCH_HEAD\"\n> anymore.  So I do not think such a change will be an improvement.\n\nUnless dwim_ref() is updated to handle FETCH_HEAD specially, and\nreturn not the first SHA1, but the one not marked \"not-for-merge\".\nThen the UI would at least be consistent, but this would not be\nbackward compatible.\n\nj.\n"},{"id":"105181","messageId":"alpine.DEB.1.00.0902171821190.6185@intel-tinevez-2-302","threadId":"17841","inReplyTo":"76718490902170914p6258b77ak81318f13757f0dfd@mail.gmail.com","subject":"Re: FETCH_HEAD question","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-02-17T17:22:47Z","receivedAt":"2009-02-17T17:22:47Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Tue, 17 Feb 2009, Jay Soffian wrote:\n\n> On Tue, Feb 17, 2009 at 3:35 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> > Now to something totally useless.\n> >\n> > After reading the builtin-merge.c and original git-merge.sh (now in\n> > contrib/examples) script, I think it could have done something entirely\n> > different.\n> >\n> > It could have done this instead.\n> >\n> >        sed -e '/       not-for-merge   /d'\n> >\n> > to learn the commits and their human-readable origins, and it could have\n> > tried to reproduce what \"git pull\" did when it invoked git-merge using\n> > that information.  Then you could use this workflow:\n> >\n> >        $ git pull <possibly with arguments>\n> >        ... oops, conflicted and is very messy.\n> >        ... I tried to resolve, but failed and made the mess even worse.\n> >        ... Let's start over.\n> >        $ git reset --hard\n> >        ... FETCH_HEAD knows which refs are for merging\n> >        $ git merge FETCH_HEAD\n> >\n> > That is, no matter what the arguments were for the initial \"git pull\",\n> > what should be merged is recorded in FETCH_HEAD, and that is how you can\n> > retry the merge without refetching over the network.\n> >\n> > But such a change makes FETCH_HEAD different from what it traditionally\n> > meant, and does that only to \"git merge\", making the result very\n> > inconsistent.  For example, \"git log ..FETCH_HEAD\" will still use the\n> > object name on the first line, and it won't be a way to convince yourself\n> > that the changes are sensible and it is Ok to run \"git merge FETCH_HEAD\"\n> > anymore.  So I do not think such a change will be an improvement.\n> \n> Unless dwim_ref() is updated to handle FETCH_HEAD specially, and\n> return not the first SHA1, but the one not marked \"not-for-merge\".\n> Then the UI would at least be consistent, but this would not be\n> backward compatible.\n\nYou cannot fix parsing FETCH_HEAD as a ref (and neither will you be able \nto do with PUSH_HEAD), as it can contain _more_ than one SHA-1s.  This \nstill holds true when ignoring the not-for-merge lines, as an octopus is\na quite real possibility.\n\nCiao,\nDscho\n"},{"id":"105186","messageId":"76718490902170934u5e2c17ffl7599ddeb5ee59812@mail.gmail.com","threadId":"17841","inReplyTo":"alpine.DEB.1.00.0902171821190.6185@intel-tinevez-2-302","subject":"Re: FETCH_HEAD question","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2009-02-17T17:34:18Z","receivedAt":"2009-02-17T17:34:18Z","isPatch":false,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"On Tue, Feb 17, 2009 at 12:22 PM, Johannes Schindelin\n<Johannes.Schindelin@gmx.de> wrote:\n>> Unless dwim_ref() is updated to handle FETCH_HEAD specially, and\n>> return not the first SHA1, but the one not marked \"not-for-merge\".\n>> Then the UI would at least be consistent, but this would not be\n>> backward compatible.\n>\n> You cannot fix parsing FETCH_HEAD as a ref (and neither will you be able\n> to do with PUSH_HEAD), as it can contain _more_ than one SHA-1s.  This\n> still holds true when ignoring the not-for-merge lines, as an octopus is\n> a quite real possibility.\n\nAn even better argument against than it not being backward compatible. :-)\n\nAnd there is no PUSH_HEAD.\n\nj.\n"},{"id":"105231","messageId":"alpine.DEB.1.00.0902172357450.10279@pacific.mpi-cbg.de","threadId":"17841","inReplyTo":"76718490902170934u5e2c17ffl7599ddeb5ee59812@mail.gmail.com","subject":"PUSH_HEAD, was Re: FETCH_HEAD question","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-02-17T22:58:13Z","receivedAt":"2009-02-17T22:58:13Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Tue, 17 Feb 2009, Jay Soffian wrote:\n\n> On Tue, Feb 17, 2009 at 12:22 PM, Johannes Schindelin\n> <Johannes.Schindelin@gmx.de> wrote:\n> >> Unless dwim_ref() is updated to handle FETCH_HEAD specially, and\n> >> return not the first SHA1, but the one not marked \"not-for-merge\".\n> >> Then the UI would at least be consistent, but this would not be\n> >> backward compatible.\n> >\n> > You cannot fix parsing FETCH_HEAD as a ref (and neither will you be able\n> > to do with PUSH_HEAD), as it can contain _more_ than one SHA-1s.  This\n> > still holds true when ignoring the not-for-merge lines, as an octopus is\n> > a quite real possibility.\n> \n> An even better argument against than it not being backward compatible. :-)\n> \n> And there is no PUSH_HEAD.\n\nHeh, that's why I used the future tense :-)\n\nCiao,\nDscho\n"},{"id":"105241","messageId":"7vab8k39ze.fsf@gitster.siamese.dyndns.org","threadId":"17841","inReplyTo":"alpine.DEB.1.00.0902172357450.10279@pacific.mpi-cbg.de","subject":"Re: PUSH_HEAD, was Re: FETCH_HEAD question","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-02-17T23:43:49Z","receivedAt":"2009-02-17T23:43:49Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> On Tue, 17 Feb 2009, Jay Soffian wrote:\n>\n>> On Tue, Feb 17, 2009 at 12:22 PM, Johannes Schindelin\n>> <Johannes.Schindelin@gmx.de> wrote:\n>> >> Unless dwim_ref() is updated to handle FETCH_HEAD specially, and\n>> >> return not the first SHA1, but the one not marked \"not-for-merge\".\n>> >> Then the UI would at least be consistent, but this would not be\n>> >> backward compatible.\n>> >\n>> > You cannot fix parsing FETCH_HEAD as a ref (and neither will you be able\n>> > to do with PUSH_HEAD), as it can contain _more_ than one SHA-1s.  This\n>> > still holds true when ignoring the not-for-merge lines, as an octopus is\n>> > a quite real possibility.\n>> \n>> An even better argument against than it not being backward compatible. :-)\n>> \n>> And there is no PUSH_HEAD.\n>\n> Heh, that's why I used the future tense :-)\n\nFETCH_HEAD is something the user who is sitting in front of the repository\ncontrols with \"git fetch\" into it.  The objects referenced from it is not\npart of the \"reachable\" set, and expectation is that anything that\nrequires the objects will happen before that user decides to actively go\nprune unreachable objects.\n\nPUSH_HEAD is quite different, and it needs to be handled a lot more\ncarefully.\n\nWe have been looking at denyCurrentBranch as a way to capture gremlin\nupdates and prevent it from confusing the end user, but PUSH_HEAD is more\nlike a pull request in reverse.  The necessary object transfer part has\nbeen already done, and the tip commit waits for the final merge step to\npick it up.  You might want a loud notification that tells you that there\nare outstanding reverse pull requests waiting to be picked up.  Its need\nto protect the objects pushed from pruning is stronger than that of\nFETCH_HEAD.\n\nWhen PUSH_HEAD is in use for a receiving repository, we would intercept\npushes to certain refs, and instead of updating them, append a record in\nthe PUSH_HEAD file.  Each entry of the file would record the object name\nand who pushed it from where and for which branch.  A new front-end\ncommand to deal with PUSH_HEAD would allow the user to:\n\n * browse them,\n\n * choose one of them and comply, by checking out the destination branch\n   and performing the merge,\n\n * choose one of them and discard, or\n\n * leave undecided.\n\nEarlier I've considered introducing the notion of (per-ref) split head.\nForgetting the presense of packed-refs for now, when a gremlin push tries\nto update a ref that is the current branch, you would instead of\noverwriting the ref (that is 40-byte hexadecimal SHA-1 plus LF), append it\n(making it contain two such lines).  Bash completion and friends can\nnotice the situation and say \"Your HEAD is split by a gremlin push\", and\nthe the user can choose to \"git merge\" the two (or more) commits recorded\nin the ref to get the split head merged again (optionally, if the work\ntree and the index is clean, and if the object the push is trying to\noverwrite the HEAD with is a descendant of the HEAD, then you can allow it\nto overwrite and run \"reset --hard\" afterwards, instead of splitting the\nhead).  I think Hg does something like that, and I think PUSH_HEAD is\nnicer than outright \"you are not allowed to push into this branch\",\nbecause the users already understand how a pull in response to a pull\nrequest works as a workflow.\n\nHaving said that, there need to be clear and sane semantics defined to\ntell which push should go to PUSH_HEAD file and which should directly go\nto the underlying ref.  It is probably the easiest to explain if all\npushes to local refs are redirected to PUSH_HEAD when the repository is\nnon-bare, but it means a non-bare repository cannot be used as the central\nshared repository for everybody to meet and swap with push-pull.  We could\nonly redirect push to the checked-out branch to PUSH_HEAD, but then that\nwould introduce an inconsistency between checked-out branches and others\nfrom fetchers' point of view; pushes to some branches are observable from\nthe outside while pushes to one special branch (the checked-out one) are\nnot.\n"},{"id":"105251","messageId":"76718490902171629x78b5057aw5e00ba22bfb8b8b0@mail.gmail.com","threadId":"17841","inReplyTo":"7vab8k39ze.fsf@gitster.siamese.dyndns.org","subject":"Re: PUSH_HEAD, was Re: FETCH_HEAD question","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2009-02-18T00:29:35Z","receivedAt":"2009-02-18T00:29:35Z","isPatch":false,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"On Tue, Feb 17, 2009 at 6:43 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Having said that, there need to be clear and sane semantics defined to\n> tell which push should go to PUSH_HEAD file and which should directly go\n> to the underlying ref.  It is probably the easiest to explain if all\n> pushes to local refs are redirected to PUSH_HEAD when the repository is\n> non-bare, but it means a non-bare repository cannot be used as the central\n> shared repository for everybody to meet and swap with push-pull.  We could\n> only redirect push to the checked-out branch to PUSH_HEAD, but then that\n> would introduce an inconsistency between checked-out branches and others\n> from fetchers' point of view; pushes to some branches are observable from\n> the outside while pushes to one special branch (the checked-out one) are\n> not.\n\nThis is along the lines of what I was thinking. However, I have also\nbeen thinking of an alternative. It would go something like this:\n\n$ git init --hybrid\n\nThis would basically setup a repository that is a combination of bare\nand non-bare and would act like having a pair or repositories. i.e.\nGiven,\n\n$ mkdir project\n$ cd project\n$ git init\n$ touch file && git add file && git commit -m initial\n$ git clone --bare file://$(pwd) ../project-public.git\n$ git remote add public ../project-public.git\n$ git config branch.master.remote public\n$ git config branch.master.merge refs/heads/master\n\nI don't mean to suggest that git init --hybrid would literally create\ntwo repositories. Rather, it would create a single repo that acts like\nthe above two. You'd \"git push\" to publish a branch and \"git pull\" to\nintegrate any pushed-in changes. refs/heads in such a repo would never\nreceive outside changes directly, nor would changes to refs/heads be\nexternally visible until published via push.\n\nThis would typically be used in the mothership/satellite scenario,\nwhere the mothership repo is setup with --hybrid and the satellite is\njust a normal clone.\n\nBut maybe this is a lot of work w/little reward.\n\nj.\n"},{"id":"105250","messageId":"alpine.DEB.1.00.0902180122440.10279@pacific.mpi-cbg.de","threadId":"17841","inReplyTo":"7vab8k39ze.fsf@gitster.siamese.dyndns.org","subject":"Re: PUSH_HEAD, was Re: FETCH_HEAD question","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-02-18T00:30:00Z","receivedAt":"2009-02-18T00:30:00Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Tue, 17 Feb 2009, Junio C Hamano wrote:\n\n> FETCH_HEAD is something the user who is sitting in front of the \n> repository controls with \"git fetch\" into it.  The objects referenced \n> from it is not part of the \"reachable\" set, and expectation is that \n> anything that requires the objects will happen before that user decides \n> to actively go prune unreachable objects.\n> \n> PUSH_HEAD is quite different, and it needs to be handled a lot more \n> carefully.\n\nWell, when I talked about the push equivalent of FETCH_HEAD I really meant \nthat it be exactly that.  No additional taking care, that's the user's \nresponsibility.\n\nI got carried away with the \"2nd push will not need to push the objects \nagain\", and in the meantime I think that should not be the case.\n\nThe main use for it I had in mind was to have some obviously temporary \n\"ref\" that you could push to.\n\nHowever, I think that would not bode well, as receive.denyCurrentBranch \nwill error out early, and rightfully so.\n\nThe way out I _could_ think of right now is to have a REFUSED_PUSH_HEAD \n_just_ for the denyCurrentBranch case, but it's bedtime for lil' Dscho, so \nI cannot think clearly about that today.\n\nCiao,\nDscho \"who will be dreaming of detached, split and pushed heads all night long\"\n"}]}