{"thread":{"id":"19137","subject":"question about a merge result","startedAt":"2009-04-30T12:21:07Z","lastAt":"2009-05-01T16:27:36Z","messageCount":7,"participants":["Francis Moreau","Michael Gaber","Jeff King","Björn Steinbrink","Daniel Barkalow"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"112759","messageId":"38b2ab8a0904300521m9e31867j7848135acfae0faa@mail.gmail.com","threadId":"19137","inReplyTo":null,"subject":"question about a merge result","fromName":"Francis Moreau","fromEmail":"francis.moro@gmail.com","sentAt":"2009-04-30T12:21:07Z","receivedAt":"2009-04-30T12:21:07Z","isPatch":false,"sender":{"key":"francis.moro@gmail.com","avatar":null},"body":"Hello,\n\nI'm a little bit confused about a merge I have done and the result\nsuprised me. Thinking about it I'm still not convinced what should be\nthe result.\n\nHere's the use case:\n\n$ mkdir test-git && cd test-git\n$ date > A\n$ date > B\n$ git init\n$ git add .\n$ git commit -m \"Init\"\n\nSo far I just created a repo with 2 files A and B\n\n$ git branch b1\n$ git rm B\n$ git commit -m \"remove B\"\n\nNow I created a branch 'b1' and remove B file in master branch\n\n$ git checkout b1\n$ git rm B\n$ git commit -m \"remove B\"\n$ git revert HEAD\n\nNow on 'b1' I did the same as master but I thought that removing B was\na bad idea so I revert the previous commit\n\n$ git checkout master\n$ git pull . b1\n$ ls B\nls: cannot access B: No such file or directory\n\nSo merging 'b1' into master removed the B file even if in branch 'b1'\nI restored it.\n\nCould anybody explain me why this is the correct behaviour and why not\nfile 'B' is not restored as it was done in branch 'b1' ?\n\nthanks\n-- \nFrancis\n"},{"id":"112760","messageId":"49F99AE3.5090406@gmx.net","threadId":"19137","inReplyTo":"38b2ab8a0904300521m9e31867j7848135acfae0faa@mail.gmail.com","subject":"Re: question about a merge result","fromName":"Michael Gaber","fromEmail":"michael.gaber@gmx.net","sentAt":"2009-04-30T12:34:43Z","receivedAt":"2009-04-30T12:34:43Z","isPatch":false,"sender":{"key":"michael.gaber@gmx.net","avatar":null},"body":"Francis Moreau schrieb:\n> Hello,\n> \n> I'm a little bit confused about a merge I have done and the result\n> suprised me. Thinking about it I'm still not convinced what should be\n> the result.\n> \n> Here's the use case:\n> \n> $ mkdir test-git && cd test-git\n> $ date > A\n> $ date > B\n> $ git init\n> $ git add .\n> $ git commit -m \"Init\"\n> \n> So far I just created a repo with 2 files A and B\n> \n> $ git branch b1\n> $ git rm B\n> $ git commit -m \"remove B\"\n> \n> Now I created a branch 'b1' and remove B file in master branch\n> \n> $ git checkout b1\n> $ git rm B\n> $ git commit -m \"remove B\"\n> $ git revert HEAD\n> \n> Now on 'b1' I did the same as master but I thought that removing B was\n> a bad idea so I revert the previous commit\n> \n> $ git checkout master\n> $ git pull . b1\n> $ ls B\n> ls: cannot access B: No such file or directory\n> \n> So merging 'b1' into master removed the B file even if in branch 'b1'\n> I restored it.\n> \n> Could anybody explain me why this is the correct behaviour and why not\n> file 'B' is not restored as it was done in branch 'b1' ?\n> \n> thanks\n\nwell, I'd say the thing is, that in b1 there is no change at all to the\ntree anymore, so when applied to master (without B) there is no b restored\n"},{"id":"112763","messageId":"20090430142635.GB23550@coredump.intra.peff.net","threadId":"19137","inReplyTo":"49F99AE3.5090406@gmx.net","subject":"Re: question about a merge result","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2009-04-30T14:26:35Z","receivedAt":"2009-04-30T14:26:35Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Apr 30, 2009 at 02:34:43PM +0200, Michael Gaber wrote:\n\n> > So merging 'b1' into master removed the B file even if in branch 'b1'\n> > I restored it.\n> > \n> > Could anybody explain me why this is the correct behaviour and why not\n> > file 'B' is not restored as it was done in branch 'b1' ?\n> \n> well, I'd say the thing is, that in b1 there is no change at all to the\n> tree anymore, so when applied to master (without B) there is no b restored\n\nThat is exactly it. Git's 3-way merge doesn't look at the intervening\nhistory at all. It looks _only_ at the two endpoints and their\nmerge-base (well, that is a bit of a simplification, as there may be\nmultiple merge-bases, but it is what is happening here).\n\n-Peff\n"},{"id":"112769","messageId":"38b2ab8a0904300805j5ce19617mdda3254c37d06d38@mail.gmail.com","threadId":"19137","inReplyTo":"20090430142635.GB23550@coredump.intra.peff.net","subject":"Re: question about a merge result","fromName":"Francis Moreau","fromEmail":"francis.moro@gmail.com","sentAt":"2009-04-30T15:05:19Z","receivedAt":"2009-04-30T15:05:19Z","isPatch":false,"sender":{"key":"francis.moro@gmail.com","avatar":null},"body":"On Thu, Apr 30, 2009 at 4:26 PM, Jeff King <peff@peff.net> wrote:\n> On Thu, Apr 30, 2009 at 02:34:43PM +0200, Michael Gaber wrote:\n>\n>> > So merging 'b1' into master removed the B file even if in branch 'b1'\n>> > I restored it.\n>> >\n>> > Could anybody explain me why this is the correct behaviour and why not\n>> > file 'B' is not restored as it was done in branch 'b1' ?\n>>\n>> well, I'd say the thing is, that in b1 there is no change at all to the\n>> tree anymore, so when applied to master (without B) there is no b restored\n>\n> That is exactly it. Git's 3-way merge doesn't look at the intervening\n> history at all. It looks _only_ at the two endpoints and their\n> merge-base (well, that is a bit of a simplification, as there may be\n> multiple merge-bases, but it is what is happening here).\n>\n\nWell, obviously it's how git works since it's what I got.\n\nBut the question was more about if the cortectness of the end result:\nshould 'B' removed after the merge.\n\nIOW if someone works on its own branch remove B file and thought it\nwas a bad idea and restore it whereas another person remove B file but\nmiss the fact that it was a bad idea, does the merge should silently\nremove B file ?\n\n-- \nFrancis\n"},{"id":"112771","messageId":"20090430153917.GB18940@atjola.homenet","threadId":"19137","inReplyTo":"38b2ab8a0904300805j5ce19617mdda3254c37d06d38@mail.gmail.com","subject":"Re: question about a merge result","fromName":"Björn Steinbrink","fromEmail":"b.steinbrink@gmx.de","sentAt":"2009-04-30T15:39:17Z","receivedAt":"2009-04-30T15:39:17Z","isPatch":false,"sender":{"key":"b.steinbrink@gmx.de","avatar":"https://avatars.githubusercontent.com/u/230962?v=4"},"body":"On 2009.04.30 17:05:19 +0200, Francis Moreau wrote:\n> On Thu, Apr 30, 2009 at 4:26 PM, Jeff King <peff@peff.net> wrote:\n> > On Thu, Apr 30, 2009 at 02:34:43PM +0200, Michael Gaber wrote:\n> >\n> >> > So merging 'b1' into master removed the B file even if in branch 'b1'\n> >> > I restored it.\n> >> >\n> >> > Could anybody explain me why this is the correct behaviour and why not\n> >> > file 'B' is not restored as it was done in branch 'b1' ?\n> >>\n> >> well, I'd say the thing is, that in b1 there is no change at all to the\n> >> tree anymore, so when applied to master (without B) there is no b restored\n> >\n> > That is exactly it. Git's 3-way merge doesn't look at the intervening\n> > history at all. It looks _only_ at the two endpoints and their\n> > merge-base (well, that is a bit of a simplification, as there may be\n> > multiple merge-bases, but it is what is happening here).\n> >\n> \n> Well, obviously it's how git works since it's what I got.\n> \n> But the question was more about if the cortectness of the end result:\n> should 'B' removed after the merge.\n> \n> IOW if someone works on its own branch remove B file and thought it\n> was a bad idea and restore it whereas another person remove B file but\n> miss the fact that it was a bad idea, does the merge should silently\n> remove B file ?\n\nYou can also have that in the opposite direction. You make a bugfix in\nyour \"master\" branch, then cherry-pick that to \"maint\", but later\nrealize that you actually can't backport it like and and revert the\ncherry-pick.  Then, later, you go to merge \"maint\" to \"master\" (to get\nother bugfixes that were done directly on \"maint\"): Should the bugfix be\nreverted on \"master\"? Obviously not.\n\ngit takes an approach that's easy to understand: Look at the changes\nthat the branch made compared to the common ancestor and apply those.\nAnd for a \"do it and then revert it\" case, the answer is: There are no\nchanges.\n\nBjörn\n"},{"id":"112773","messageId":"20090430154240.GA27416@coredump.intra.peff.net","threadId":"19137","inReplyTo":"38b2ab8a0904300805j5ce19617mdda3254c37d06d38@mail.gmail.com","subject":"Re: question about a merge result","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2009-04-30T15:42:40Z","receivedAt":"2009-04-30T15:42:40Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Apr 30, 2009 at 05:05:19PM +0200, Francis Moreau wrote:\n\n> Well, obviously it's how git works since it's what I got.\n\nYes, I meant also \"this is what it is supposed to do, by design\".\n\n> But the question was more about if the cortectness of the end result:\n> should 'B' removed after the merge.\n> \n> IOW if someone works on its own branch remove B file and thought it\n> was a bad idea and restore it whereas another person remove B file but\n> miss the fact that it was a bad idea, does the merge should silently\n> remove B file ?\n\nYes, it should be removed. And it has nothing to do with removal. Both\nbranches performed some action, but only one reverted it. Thus you still\nhave one branch wanting to make the change, and the other side leaving\nit alone (in aggregate). So we want to take the changed side.\n\nThe only other thing that might make sense would be a conflict (because\nboth sides touched the same area and ended with different results). Git\ndoesn't try to find such a conflict because:\n\n  1. Fundamentally, git cares about endpoints, not changelogs. So by\n     design, you can arrive at the same tree state by many different\n     routes and the merge will still happen in the same way.\n\n  2. Finding such a conflict in the general case would be quite\n     expensive, because you have to track every bit of content changed\n     on one branch through every commit on the other branch, to see if\n     they ever overlap.\n\nIf you want the result of the merge to keep it, you should do one of:\n\n  - revert the removal in _both_ branches\n\n  - merge with \"--no-commit\", add it back in, and then commit. The\n    resulting commit will be a merge commit with the state you specify.\n\n  - merge the early part of one branch, with the removal, into the other\n    branch. Then \"removed\" becomes your basis for comparison, and then\n    when you re-merge, the branch that re-adds it will be the only\n    change.\n\n-Peff\n"},{"id":"112827","messageId":"alpine.LNX.2.00.0905011210140.2147@iabervon.org","threadId":"19137","inReplyTo":"38b2ab8a0904300805j5ce19617mdda3254c37d06d38@mail.gmail.com","subject":"Re: question about a merge result","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2009-05-01T16:27:36Z","receivedAt":"2009-05-01T16:27:36Z","isPatch":false,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Thu, 30 Apr 2009, Francis Moreau wrote:\n\n> But the question was more about if the cortectness of the end result:\n> should 'B' removed after the merge.\n> \n> IOW if someone works on its own branch remove B file and thought it\n> was a bad idea and restore it whereas another person remove B file but\n> miss the fact that it was a bad idea, does the merge should silently\n> remove B file ?\n\nConsider that deciding to remove a file can happen for a variety of \nreasons. Maybe one branch wiped it out accidentally and restored it, while \nthe other did a bunch of work to make it obsolete and then removed it \nintentionally. There's no reason to think that the reason behind reverting \nthe delete on one branch applies to the other delete.\n\nNow, if the \"b1\" branch had gotten the delete from \"master\" by merging the \nsame commit, and had reverted the commit that deleted the file, then git \nshould (and does) include the file in the merge result, because then some \nuser saw that particular deletion and decided it was wrong and reverted \nit. (Of course, git doesn't actually consider this in its merge algorithm, \nbut, for clever mathematical reasons, what it does is equivalent.)\n\n\t-Daniel\n*This .sig left intentionally blank*\n"}]}