{"thread":{"id":"42207","subject":"remotes","startedAt":"2016-05-03T16:16:24Z","lastAt":"2016-05-04T08:11:14Z","messageCount":6,"participants":["Lev","Junio C Hamano","Kovacs Levente","Stefan Beller"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"285338","messageId":"20160503181624.1504eb0a@laborpc","threadId":"42207","inReplyTo":null,"subject":"remotes","fromName":"Lev","fromEmail":"leventelist@gmail.com","sentAt":"2016-05-03T16:16:24Z","receivedAt":"2016-05-03T16:16:24Z","isPatch":false,"sender":{"key":"leventelist@gmail.com","avatar":null},"body":"Dear List,\n\n\nI accidentally added a remote of another repository to my config file. And so I\nmerged two different repositories together. Is there any real user case for\nthis? Is there any way to prevent this happening?\n\nThanks,\nLev\n"},{"id":"285374","messageId":"xmqqshxylvwh.fsf@gitster.mtv.corp.google.com","threadId":"42207","inReplyTo":"20160503181624.1504eb0a@laborpc","subject":"Re: remotes","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-05-03T20:38:22Z","receivedAt":"2016-05-03T20:38:22Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Lev <leventelist@gmail.com> writes:\n\n> I accidentally added a remote of another repository to my config file. And so I\n> merged two different repositories together. Is there any real user case for\n> this?\n\nUsing multiple remotes is a perfectly normal way in which you are\nexpected to interact with a single project with other participants.\nPerhaps there is one single authoritative and canonical repository\nwhere everybody initially clones from, and it is likely that that\nrepository is your \"origin\".  Often there are cases where another\nparticipant has a topic that is not yet ready for the mainline but\nis worth considering for early adopters and/or is solid enough for\nother project participants to build their work on.  In such cases,\nyou can add the repository of that other participant as the second\nremote and fetch from her.\n\nIt makes no sense if the two repositories hold histories of totally\nunrelated projects, of course.\n"},{"id":"285401","messageId":"20160504013624.4c51ce42@wind.levalinux.org","threadId":"42207","inReplyTo":"xmqqshxylvwh.fsf@gitster.mtv.corp.google.com","subject":"Re: remotes","fromName":"Kovacs Levente","fromEmail":"leventelist@gmail.com","sentAt":"2016-05-03T23:36:24Z","receivedAt":"2016-05-03T23:36:24Z","isPatch":false,"sender":{"key":"leventelist@gmail.com","avatar":null},"body":"On Tue, 03 May 2016 13:38:22 -0700\nJunio C Hamano <gitster@pobox.com> wrote:\n\n> Lev <leventelist@gmail.com> writes:\n> \n> > I accidentally added a remote of another repository to my config\n> > file. And so I merged two different repositories together. Is there\n> > any real user case for this?  \n> \n> Using multiple remotes is a perfectly normal way in which you are\n> expected to interact with a single project with other participants.\n> Perhaps there is one single authoritative and canonical repository\n> where everybody initially clones from, and it is likely that that\n> repository is your \"origin\".  Often there are cases where another\n> participant has a topic that is not yet ready for the mainline but\n> is worth considering for early adopters and/or is solid enough for\n> other project participants to build their work on.  In such cases,\n> you can add the repository of that other participant as the second\n> remote and fetch from her.\n\nYes, I use that feature.\n \n> It makes no sense if the two repositories hold histories of totally\n> unrelated projects, of course.\n\nWould it make sense to implement some protection against these kind of\naccidents? At least a question \"are you sure you want to merge two\nindependent repositories/branches?\"\n\nThanks,\nLev\n\n\n-- \n73 de HA5OGL\nOp.: Levente\n"},{"id":"285402","messageId":"CAGZ79kat4rW7raoXQNF2mb0nS5qF0e7yTCoSkiFe2VFJ=E_VdA@mail.gmail.com","threadId":"42207","inReplyTo":"20160504013624.4c51ce42@wind.levalinux.org","subject":"Re: remotes","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2016-05-03T23:47:47Z","receivedAt":"2016-05-03T23:47:47Z","isPatch":false,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Tue, May 3, 2016 at 4:36 PM, Kovacs Levente <leventelist@gmail.com> wrote:\n> On Tue, 03 May 2016 13:38:22 -0700\n> Junio C Hamano <gitster@pobox.com> wrote:\n>\n>> Lev <leventelist@gmail.com> writes:\n>>\n>> > I accidentally added a remote of another repository to my config\n>> > file. And so I merged two different repositories together. Is there\n>> > any real user case for this?\n>>\n>> Using multiple remotes is a perfectly normal way in which you are\n>> expected to interact with a single project with other participants.\n>> Perhaps there is one single authoritative and canonical repository\n>> where everybody initially clones from, and it is likely that that\n>> repository is your \"origin\".  Often there are cases where another\n>> participant has a topic that is not yet ready for the mainline but\n>> is worth considering for early adopters and/or is solid enough for\n>> other project participants to build their work on.  In such cases,\n>> you can add the repository of that other participant as the second\n>> remote and fetch from her.\n>\n> Yes, I use that feature.\n>\n>> It makes no sense if the two repositories hold histories of totally\n>> unrelated projects, of course.\n>\n> Would it make sense to implement some protection against these kind of\n> accidents? At least a question \"are you sure you want to merge two\n> independent repositories/branches?\"\n\nA recent addition is the check for unrelated histories via checking for added\nroot commits (i.e. commits with no parent) and refusing to merge them\nby default.\nyou need to pass --allow-unrelated-histories to merge.\n\nsee\nhttps://kernel.googlesource.com/pub/scm/git/git/+/e379fdf34fee96cd205be83ff4e71699bdc32b18\n\n>\n> Thanks,\n> Lev\n>\n>\n> --\n> 73 de HA5OGL\n> Op.: Levente\n"},{"id":"285424","messageId":"xmqqk2jajobz.fsf@gitster.mtv.corp.google.com","threadId":"42207","inReplyTo":"CAGZ79kat4rW7raoXQNF2mb0nS5qF0e7yTCoSkiFe2VFJ=E_VdA@mail.gmail.com","subject":"Re: remotes","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-05-04T07:04:48Z","receivedAt":"2016-05-04T07:04:48Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Stefan Beller <sbeller@google.com> writes:\n\n> A recent addition is the check for unrelated histories via\n> checking for added root commits (i.e. commits with no parent) and\n> refusing to merge them by default.  you need to pass\n> --allow-unrelated-histories to merge.\n>\n> see\n> https://kernel.googlesource.com/pub/scm/git/git/+/e379fdf34fee96cd205be83ff4e71699bdc32b18\n\nThat commit however is not about \"checking for added root commits\",\nwhich would be way more expensive to compute.  That commit is merely\nabout detecting that the other history does not have _any_ relation\nto ours.\n\nThe difference is in this sequence.\n\n (1) Alice owns the canonical history.\n (2) Bob copies Alice's tip tree without history, starts a\n     different root, and builds some history.\n (3) Alice builds some more history.\n (4) Bob pulls from Alice.  The check in e379fdf3 triggers here, but\n     Bob can override it.\n (5) Alice builds even more history.\n (6) Bob also builds even more history.\n (7) Bob asks Alice to pull from him.\n (8) Alice pulls from Bob.  The common ancestor discovery finds the\n     merge base between (4) and (5), which is (3).\n\n    ---(1)---(3)---(5)---(8)\n                \\        /\n          (2)---(4)---(6)\n\nThe history traversal is done at (8) to find merge-base for two\npurposes.  One is to find the common ancestor to use in 3-way merge,\nand the other is for the check introduced by e379fdf3.  It stops at\nfinding (3), and does not traverse the history all the way down to\n(2).  But in order for Alice to notice that the merge would pull a\nnew root Alice never has seen, i.e. (2), a traversal needs to\ncontinue down to the root of other's history.\n\nNaively, it would be running\n\n\trev-list --max-parents=0 ^HEAD MERGE_HEAD\n\nand see if the result is not empty, in which case you found (2).\nBut that is way too expensive unless (2) is relatively shallow.\n"},{"id":"285433","messageId":"xmqq1t5ijl99.fsf@gitster.mtv.corp.google.com","threadId":"42207","inReplyTo":"xmqqk2jajobz.fsf@gitster.mtv.corp.google.com","subject":"Re: remotes","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-05-04T08:11:14Z","receivedAt":"2016-05-04T08:11:14Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> The difference is in this sequence.\n>\n>  (1) Alice owns the canonical history.\n>  (2) Bob copies Alice's tip tree without history, starts a\n>      different root, and builds some history.\n>  (3) Alice builds some more history.\n>  (4) Bob pulls from Alice.  The check in e379fdf3 triggers here, but\n>      Bob can override it.\n>  (5) Alice builds even more history.\n>  (6) Bob also builds even more history.\n>  (7) Bob asks Alice to pull from him.\n>  (8) Alice pulls from Bob.  The common ancestor discovery finds the\n>      merge base between (4) and (5), which is (3).\n\nCorrection.  That merge-base is between (6) and (5); I renumbered\nthe steps while writing the document and failed to update the\nreference.\n\n>     ---(1)---(3)---(5)---(8)\n>                 \\        /\n>           (2)---(4)---(6)\n>\n> The history traversal is done at (8) to find merge-base for two\n> purposes.  One is to find the common ancestor to use in 3-way merge,\n> and the other is for the check introduced by e379fdf3.  It stops at\n> finding (3), and does not traverse the history all the way down to\n> (2).  But in order for Alice to notice that the merge would pull a\n> new root Alice never has seen, i.e. (2), a traversal needs to\n> continue down to the root of other's history.\n>\n> Naively, it would be running\n>\n> \trev-list --max-parents=0 ^HEAD MERGE_HEAD\n>\n> and see if the result is not empty, in which case you found (2).\n> But that is way too expensive unless (2) is relatively shallow.\n\nA not-so-naive optimization Linus alluded to in the discussion that\nwas a tangent of e379fdf3 was to teach unpack-objects and index-pack\nto report when they see any root commits in the payload.  When Alice\npulls from Bob at (8), one of these two programs would already be\nexamining every object received from Bob's history, and they can\nnotice the presense of (2), a new root commit, and report it to the\ncaller with minimum additional cost.\n\nUnfortunately that approach will not work in the general case of\n\"fetch to examine first and then decide to merge\" workflow, as there\nis no medium the first step, i.e. \"fetch\", can use to convey the\nfact that it saw a new root to the later step, i.e. \"merge\".  Doubly\nunfortunate is that \"git pull\" is in fact implemented in terms of\nhandling that general case.  We _might_ be able to futz with the\nfile format used in FETCH_HEAD to help \"git pull\", but that would\nnot help a true user-space \"git fetch $there master:there/master\"\nfollowed by \"git merge there/master\" workflow.\n"}]}