{"thread":{"id":"51452","subject":"Unexpected or wrong ff, no-ff and ff-only behaviour","startedAt":"2019-07-09T09:43:11Z","lastAt":"2019-07-19T11:00:50Z","messageCount":20,"participants":["usbuser@mailbox.org","Junio C Hamano","Roland Jäger","Elijah Newren","Bryan Turner","Sergey Organov","brian m. carlson"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"378720","messageId":"423596682.8516.1562665372094@office.mailbox.org","threadId":"51452","inReplyTo":null,"subject":"Unexpected or wrong ff, no-ff and ff-only behaviour","fromName":"","fromEmail":"usbuser@mailbox.org","sentAt":"2019-07-09T09:42:51Z","receivedAt":"2019-07-09T09:43:11Z","isPatch":false,"sender":{"key":"usbuser@mailbox.org","avatar":null},"body":"Hello,\n\nI'm rather confused about --ff, --no-ff and --ff-only. They seam to be all mutual exclusive while the man page documentation and help reads as if only the first two are mutual exclusive, while the later is a check that can be enabled additionally to the former ones. I'm not sure why I couldn't find anything online about this issue.\n\nThe expected behaviour would be that a git merge --ff-only --no-ff only accepts merges where HEAD is up to date and generates then a merge commit. The observed behaviour is that a merge with conflict / non up to data HEAD is entered. If the two flags are swapped it can be observed that no merge commit is created and the branch is fast forwarded.\n\nSincerely,\neyenseo\n"},{"id":"378724","messageId":"xmqqa7dnw9b1.fsf@gitster-ct.c.googlers.com","threadId":"51452","inReplyTo":"423596682.8516.1562665372094@office.mailbox.org","subject":"Re: Unexpected or wrong ff, no-ff and ff-only behaviour","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-07-09T14:51:14Z","receivedAt":"2019-07-09T14:51:19Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"usbuser@mailbox.org writes:\n\n> I'm rather confused about --ff, --no-ff and --ff-only. They seam\n> to be all mutual exclusive...\n\nA clean result left by \"git merge\" can be either a fast-forward, or\na real merge (i.e. 2 possible outcomes).\n\nThe --ff option lets you say \"If the other history I am attempting\nto merge is a descendant of the current commit, not creating a real\nmerge and instead fast-forwarding is permitted\".  As this is the\ndefault, case you actually type --ff on the command line is rather\nlimited (e.g. to countermand an earlier --no-ff on the command\nline).\n\nThe --no-ff option lets you say \"I never accept a fast-forward as\nthe result; please make a real merge instead, even if it is\nredundant\".\n\nThe --ff-only option lets you say \"I never accept a real merge as \nthe result; please fail if this does not fast-forward\".\n\nSo, the only \"real\" options are between --[no-]ff (which allows or\ndisallows one of the two possible outcomes, which is \"fast-forward\")\nand [--ff-only] (which allows or disallows the other one of the two\npossible outcomes, which is \"real merge\").\n"},{"id":"378725","messageId":"1152121968.7459.1562688927235@office.mailbox.org","threadId":"51452","inReplyTo":"xmqqa7dnw9b1.fsf@gitster-ct.c.googlers.com","subject":"Re: Unexpected or wrong ff, no-ff and ff-only behaviour","fromName":"Roland Jäger","fromEmail":"eyenseo@mailbox.org","sentAt":"2019-07-09T16:15:27Z","receivedAt":"2019-07-09T16:15:41Z","isPatch":false,"sender":{"key":"eyenseo@mailbox.org","avatar":null},"body":"Thanks for answering Junio. \n\nI get what git does. But I believe that either the documentation ist wrong/ambiguous or --no-ff and --ff-only should be able to be combined and either should be fixed - preferably the later. What I want to say to git is \"I never accept a real merge; please make a merge commit, even if it is redundant/empty\". And I believe that github and gitlab allow to configure something like that.\n\nMy manpage tells me the following:\n\n--ff When the merge resolves as a fast-forward, only update the branch pointer, without creating a merge commit. This is the default behavior.\n=> Allow either\n\n--no-ff Create a merge commit even when the merge resolves as a fast-forward. This is the default behaviour when merging an annotated (and possibly signed) tag that is not stored in its natural place in refs/tags/ hierarchy.\n=> Always create a commit, even when FF\n\n--ff-only Refuse to merge and exit with a non-zero status unless the current HEAD is already up to date or the merge can be resolved as a fast-forward.\n=> Fail if FF is not possible\n\n \n\nman page: \nOn 9 July 2019 16:51:14 CEST, Junio C Hamano <gitster@pobox.com> wrote:> usbuser@mailbox.org writes:\n> \n> > I'm rather confused about --ff, --no-ff and --ff-only. They seam\n> >      \n> > to be all mutual exclusive...\n> A clean result left by \"git merge\" can be either a fast-forward, or\n> a real merge (i.e. 2 possible outcomes).\n> \n> The --ff option lets you say \"If the other history I am attempting\n> to merge is a descendant of the current commit, not creating a real\n> merge and instead fast-forwarding is permitted\".  As this is the\n> default, case you actually type --ff on the command line is rather\n> limited (e.g. to countermand an earlier --no-ff on the command\n> line).\n> \n> The --no-ff option lets you say \"I never accept a fast-forward as\n> the result; please make a real merge instead, even if it is\n> redundant\".\n> \n> The --ff-only option lets you say \"I never accept a real merge as \n> the result; please fail if this does not fast-forward\".\n> \n> So, the only \"real\" options are between --[no-]ff (which allows or\n> disallows one of the two possible outcomes, which is \"fast-forward\")\n> and [--ff-only] (which allows or disallows the other one of the two\n> possible outcomes, which is \"real merge\").\n"},{"id":"378727","messageId":"CABPp-BHpkcOSkTrNDPGWRgSJgbqkc0PRqMqmesg7tQdS5TfMDA@mail.gmail.com","threadId":"51452","inReplyTo":"1152121968.7459.1562688927235@office.mailbox.org","subject":"Re: Unexpected or wrong ff, no-ff and ff-only behaviour","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2019-07-09T16:35:09Z","receivedAt":"2019-07-09T16:35:24Z","isPatch":false,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"Hi Roland,\n\nOn Tue, Jul 9, 2019 at 9:17 AM Roland Jäger <eyenseo@mailbox.org> wrote:\n>\n> Thanks for answering Junio.\n>\n> I get what git does. But I believe that either the documentation ist wrong/ambiguous or --no-ff and --ff-only should be able to be combined and either should be fixed - preferably the later. What I want to say to git is \"I never accept a real merge; please make a merge commit, even if it is redundant/empty\". And I believe that github and gitlab allow to configure something like that.\n\nPlease don't top-post on this list.\n\nI agree, the documentation is wrong or misleading and there is a\nwording change we could make to improve it.  But, in particular,\n--no-ff and -ff-only are completely incompatible.  A fast forward\nimplies no commits of any kind are created, while --no-ff explicitly\nrequires one to be created.  More on that below...\n\n> My manpage tells me the following:\n>\n> --ff When the merge resolves as a fast-forward, only update the branch pointer, without creating a merge commit. This is the default behavior.\n> => Allow either\n\nYes.\n\n> --no-ff Create a merge commit even when the merge resolves as a fast-forward. This is the default behaviour when merging an annotated (and possibly signed) tag that is not stored in its natural place in refs/tags/ hierarchy.\n> => Always create a commit, even when FF\n\nNot quite; I'd instead say:\n\n=> Always create a merge commit, even if FF is instead possible.\n\nIn particular, FF means there is no commit creation.  I agree the\ndocumentation needs correction here, it should be:\n\n\"--no-ff: Create a merge commit even when the merge could instead\nresolve as a fast-forward...\"\n\nWould you like to try your hand at submitting a patch with this change?\n\n> --ff-only Refuse to merge and exit with a non-zero status unless the current HEAD is already up to date or the merge can be resolved as a fast-forward.\n> => Fail if FF is not possible\n\nYes.\n\n\nHope that helps,\nElijah\n"},{"id":"378728","messageId":"275487563.12198.1562691633735@office.mailbox.org","threadId":"51452","inReplyTo":"CABPp-BHpkcOSkTrNDPGWRgSJgbqkc0PRqMqmesg7tQdS5TfMDA@mail.gmail.com","subject":"Re: Unexpected or wrong ff, no-ff and ff-only behaviour","fromName":"","fromEmail":"usbuser@mailbox.org","sentAt":"2019-07-09T17:00:33Z","receivedAt":"2019-07-09T17:00:41Z","isPatch":false,"sender":{"key":"usbuser@mailbox.org","avatar":null},"body":"> On 09 July 2019 at 18:35 Elijah Newren <newren@gmail.com> wrote:\n> \n> \n> Hi Roland,\n> \n> On Tue, Jul 9, 2019 at 9:17 AM Roland Jäger <eyenseo@mailbox.org> wrote:\n> >\n> > Thanks for answering Junio.\n> >\n> > I get what git does. But I believe that either the documentation ist wrong/ambiguous or --no-ff and --ff-only should be able to be combined and either should be fixed - preferably the later. What I want to say to git is \"I never accept a real merge; please make a merge commit, even if it is redundant/empty\". And I believe that github and gitlab allow to configure something like that.\n> \n> Please don't top-post on this list.\n> \n> I agree, the documentation is wrong or misleading and there is a\n> wording change we could make to improve it.  But, in particular,\n> --no-ff and -ff-only are completely incompatible.  A fast forward\n> implies no commits of any kind are created, while --no-ff explicitly\n> requires one to be created.  More on that below...\n> \n> > My manpage tells me the following:\n> >\n> > --ff When the merge resolves as a fast-forward, only update the branch pointer, without creating a merge commit. This is the default behavior.\n> > => Allow either\n> \n> Yes.\n> \n> > --no-ff Create a merge commit even when the merge resolves as a fast-forward. This is the default behaviour when merging an annotated (and possibly signed) tag that is not stored in its natural place in refs/tags/ hierarchy.\n> > => Always create a commit, even when FF\n> \n> Not quite; I'd instead say:\n> \n> => Always create a merge commit, even if FF is instead possible.\n> \n> In particular, FF means there is no commit creation.  I agree the\n> documentation needs correction here, it should be:\n> \n> \"--no-ff: Create a merge commit even when the merge could instead\n> resolve as a fast-forward...\"\n> \n> Would you like to try your hand at submitting a patch with this change?\n> \n> > --ff-only Refuse to merge and exit with a non-zero status unless the current HEAD is already up to date or the merge can be resolved as a fast-forward.\n> > => Fail if FF is not possible\n> \n> Yes.\n> \n> \n> Hope that helps,\n> Elijah\n\nI hope this is not-top-posting? I'm new to this and know nothing apparently.\n\nIf I were to write a patch then I would very much prefer to implement the behaviour that I expected and want to exist - either by a new flag and fixed wording, or just fixed behaviour. I guess the latter is a no go. Could you point me in the right direction where I would need to start to add such a flag?\n\nAdditionally I would also want to change the wording for --ff-only, as it currently reads as if it only performs a check (which would lead to the expected behaviour) but does more than that, as it prevents \"real merges\" altogether.\n\nThank you for your time,\nRoland\n"},{"id":"378734","messageId":"CABPp-BGPLxR7NgXRHppLy_W0c=Odhhns2RjcQ4iWKKQMz+SpDQ@mail.gmail.com","threadId":"51452","inReplyTo":"275487563.12198.1562691633735@office.mailbox.org","subject":"Re: Unexpected or wrong ff, no-ff and ff-only behaviour","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2019-07-09T20:33:33Z","receivedAt":"2019-07-09T20:33:48Z","isPatch":false,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Tue, Jul 9, 2019 at 10:00 AM <usbuser@mailbox.org> wrote:\n>\n> > On 09 July 2019 at 18:35 Elijah Newren <newren@gmail.com> wrote:\n> >\n...\n> > Hope that helps,\n> > Elijah\n>\n> I hope this is not-top-posting? I'm new to this and know nothing apparently.\n\nYep, you're doing good.\n\n> If I were to write a patch then I would very much prefer to implement the behaviour that I expected and want to exist - either by a new flag and fixed wording, or just fixed behaviour. I guess the latter is a no go. Could you point me in the right direction where I would need to start to add such a flag?\n\nWe can't break backward compatibility, so we can't change the meaning\nof the existing flags.  However, I have no idea what you want this new\nflag to do; what is the behavior you want?  The only three\npossibilities I can think of are what the three flags we are currently\ndiscussing do.\n\n> Additionally I would also want to change the wording for --ff-only, as it currently reads as if it only performs a check (which would lead to the expected behaviour) but does more than that, as it prevents \"real merges\" altogether.\n\nYou've lost me again, I think.  You expect --ff-only to only perform a\ncheck, i.e. to not update anything and thus only report on whether a\nfast-forward would be possible, but leave the branch exactly where it\nstarted no matter what?\n\nOr is it just still not clear that a fast forward by definition is not\n\"a real merge\", i.e. it means to update using a mechanism that doesn't\ninvolve creating any new commits?\n\n\nElijah\n"},{"id":"378735","messageId":"CAGyf7-FW-_4AbWE735-=7WjZAaTLHOT_QuWOoHKAjOzZCbWhFA@mail.gmail.com","threadId":"51452","inReplyTo":"CABPp-BGPLxR7NgXRHppLy_W0c=Odhhns2RjcQ4iWKKQMz+SpDQ@mail.gmail.com","subject":"Re: Unexpected or wrong ff, no-ff and ff-only behaviour","fromName":"Bryan Turner","fromEmail":"bturner@atlassian.com","sentAt":"2019-07-09T20:51:39Z","receivedAt":"2019-07-09T20:51:53Z","isPatch":false,"sender":{"key":"bturner@atlassian.com","avatar":"https://gravatar.com/avatar/16bcf3167981c1ef7c804e502642366d888a35b0d0b0a4ca01fdc442aa1acb1e?d=mp&s=160"},"body":"On Tue, Jul 9, 2019 at 1:33 PM Elijah Newren <newren@gmail.com> wrote:\n>\n> On Tue, Jul 9, 2019 at 10:00 AM <usbuser@mailbox.org> wrote:\n> >\n> > Additionally I would also want to change the wording for --ff-only, as it currently reads as if it only performs a check (which would lead to the expected behaviour) but does more than that, as it prevents \"real merges\" altogether.\n>\n> You've lost me again, I think.  You expect --ff-only to only perform a\n> check, i.e. to not update anything and thus only report on whether a\n> fast-forward would be possible, but leave the branch exactly where it\n> started no matter what?\n>\n> Or is it just still not clear that a fast forward by definition is not\n> \"a real merge\", i.e. it means to update using a mechanism that doesn't\n> involve creating any new commits?\n\nI think this is something I've seen come up on the list before[1]\n(Roland can correct me if I'm wrong). What I've seen asked for before\nis the ability to pass the combination \"--ff-only --no-ff\" and have\nthat:\n* Ensure the branch to be merged is fast-forward from the current\nbranch (i.e., to ensure no merge commit is actually necessary), but\n* Create a redundant merge commit anyway\n\nThis retains the ancestry (as in, it shows where the branches were\nmerged), but the merge is always effectively a no-op (no risk of\nunintended interactions, the sort of subtle breakages where the merge\nsucceeds but the code on each \"side\" isn't entirely compatible,\nresulting in broken compilation and/or tests and/or runtime).\n\nBest regards,\nBryan Turner\n\n[1] https://public-inbox.org/git/CAP4gbxqjHzqHhPuNK8UOwPMa46g2=vcNSk1AvGjxN8s+ou-0Dw@mail.gmail.com/\n"},{"id":"378756","messageId":"1837375396.9386.1562744956530@office.mailbox.org","threadId":"51452","inReplyTo":"CAGyf7-FW-_4AbWE735-=7WjZAaTLHOT_QuWOoHKAjOzZCbWhFA@mail.gmail.com","subject":"Re: Unexpected or wrong ff, no-ff and ff-only behaviour","fromName":"","fromEmail":"usbuser@mailbox.org","sentAt":"2019-07-10T07:49:16Z","receivedAt":"2019-07-10T07:49:46Z","isPatch":false,"sender":{"key":"usbuser@mailbox.org","avatar":null},"body":"> On 09 July 2019 at 22:51 Bryan Turner <bturner@atlassian.com> wrote:\n> \n> On Tue, Jul 9, 2019 at 1:33 PM Elijah Newren <newren@gmail.com> wrote:\n> >\n> > On Tue, Jul 9, 2019 at 10:00 AM <usbuser@mailbox.org> wrote:\n> > >\n> > > Additionally I would also want to change the wording for --ff-only, as it currently reads as if it only performs a check (which would lead to the expected behaviour) but does more than that, as it prevents \"real merges\" altogether.\n> >\n> > You've lost me again, I think.  You expect --ff-only to only perform a\n> > check, i.e. to not update anything and thus only report on whether a\n> > fast-forward would be possible, but leave the branch exactly where it\n> > started no matter what?\n> >\n> > Or is it just still not clear that a fast forward by definition is not\n> > \"a real merge\", i.e. it means to update using a mechanism that doesn't\n> > involve creating any new commits?\n> \n> I think this is something I've seen come up on the list before[1]\n> (Roland can correct me if I'm wrong). What I've seen asked for before\n> is the ability to pass the combination \"--ff-only --no-ff\" and have\n> that:\n> * Ensure the branch to be merged is fast-forward from the current\n> branch (i.e., to ensure no merge commit is actually necessary), but\n> * Create a redundant merge commit anyway\n> \n> This retains the ancestry (as in, it shows where the branches were\n> merged), but the merge is always effectively a no-op (no risk of\n> unintended interactions, the sort of subtle breakages where the merge\n> succeeds but the code on each \"side\" isn't entirely compatible,\n> resulting in broken compilation and/or tests and/or runtime).\n> \n> Best regards,\n> Bryan Turner\n> \n> [1] https://public-inbox.org/git/CAP4gbxqjHzqHhPuNK8UOwPMa46g2=vcNSk1AvGjxN8s+ou-0Dw@mail.gmail.com/\n\nThis is exactly what I was expecting/wanting, thanks for clarifying.\n"},{"id":"378764","messageId":"87y316gdnf.fsf@osv.gnss.ru","threadId":"51452","inReplyTo":"CABPp-BHpkcOSkTrNDPGWRgSJgbqkc0PRqMqmesg7tQdS5TfMDA@mail.gmail.com","subject":"Re: Unexpected or wrong ff, no-ff and ff-only behaviour","fromName":"Sergey Organov","fromEmail":"sorganov@gmail.com","sentAt":"2019-07-10T14:36:20Z","receivedAt":"2019-07-10T14:46:17Z","isPatch":false,"sender":{"key":"sorganov@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8501568?v=4"},"body":"Hi Elijah,\n\nElijah Newren <newren@gmail.com> writes:\n\n> Hi Roland,\n>\n> On Tue, Jul 9, 2019 at 9:17 AM Roland Jäger <eyenseo@mailbox.org> wrote:\n>>\n>> Thanks for answering Junio.\n>>\n>> I get what git does. But I believe that either the documentation ist\n>> wrong/ambiguous or --no-ff and --ff-only should be able to be\n>> combined and either should be fixed - preferably the later. What I\n>> want to say to git is \"I never accept a real merge; please make a\n>> merge commit, even if it is redundant/empty\". And I believe that\n>> github and gitlab allow to configure something like that.\n>\n> Please don't top-post on this list.\n>\n> I agree, the documentation is wrong or misleading and there is a\n> wording change we could make to improve it.  But, in particular,\n> --no-ff and -ff-only are completely incompatible.\n\nThey currently are compatible, but in a weird manner, see below.\n\nI'd prefer they were perfectly compatible and orthogonal, as using both\nwould be the safe way to create cleanest possible merge -- the one that\nintroduces on the mainline the /exact/ changes made on side-branch:\n\n--ff-only: tells git to refuse operation (actual merge) if FF is\nimpossible, that for this particular use-case would ensure the merge, when\nactually created, is the \"cleanest possible\" one\n\nand then\n\n--no-ff: forces git to create actual (cleanest possible) merge commit,\nthat otherwise it wouldn't, as it defaults to --ff, and --ff-only above\nensures FF is possible.\n\nRight now (in my git 2.10) it seems these options somehow cancel each\nother, that is both useless and surprising:\n\nWhen FF is possible:\n\n$ git merge --ff-only --no-ff side_branch\n\nMerge made by the 'recursive' strategy.\n[...]\n\nGood!\n\n$ git reset --hard HEAD~1\n[...]\n$ git merge --no-ff --ff-only side_branch\nUpdating eafaed6..b83db07\nFast-forward    \n[...]\n\n??? I said --no-ff: how comes you did fast-forward?!\n\nWhen FF is impossible:\n\n$ git merge --ff-only --no-ff side_branch\n\nMerge made by the 'recursive' strategy.\n[...] \n??? I said --ff-only: how comes you didn't bail out?!\n\n$ git reset --hard HEAD~1\n[...]\n$ git merge --no-ff --ff-only side_branch\nfatal: Not possible to fast-forward, aborting.\n\nGood!\n\n-- Sergey\n\ngit version 2.10.0.1.g57b01a3\n"},{"id":"378765","messageId":"xmqqtvbtu9uo.fsf@gitster-ct.c.googlers.com","threadId":"51452","inReplyTo":"CAGyf7-FW-_4AbWE735-=7WjZAaTLHOT_QuWOoHKAjOzZCbWhFA@mail.gmail.com","subject":"Re: Unexpected or wrong ff, no-ff and ff-only behaviour","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-07-10T16:34:39Z","receivedAt":"2019-07-10T16:34:54Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Bryan Turner <bturner@atlassian.com> writes:\n\n> I think this is something I've seen come up on the list before[1]\n> (Roland can correct me if I'm wrong). What I've seen asked for before\n> is the ability to pass the combination \"--ff-only --no-ff\" and have\n> that:\n> * Ensure the branch to be merged is fast-forward from the current\n> branch (i.e., to ensure no merge commit is actually necessary), but\n> * Create a redundant merge commit anyway\n>\n> This retains the ancestry (as in, it shows where the branches were\n> merged), but the merge is always effectively a no-op (no risk of\n> unintended interactions, the sort of subtle breakages where the merge\n> succeeds but the code on each \"side\" isn't entirely compatible,\n> resulting in broken compilation and/or tests and/or runtime).\n\nHmph.  I know that the above was totally outside of expected use\npattern back when --ff/--no-ff and --ff-only were invented.  As I\nstill cannot tell if the use pattern makes sense, or even is\ninternally consistent, I am not ready to say if the omission was a\nbad thing, though.  We did not omit it deliberately, but we might\nhave been lucky to omit it, which may have prevented a wrong\nworkflow from spreading.  If it is a wrong workflow, that is, and I\nam yet not sure it is not.\n\nThe \"--no-ff\" part is a way to ensure that the series of commits are\nstill grouped together after they hit the mainline of the history,\nso it expresses a wish (by the project using the use pattern) that\nthey care about topic branch workflow.  A group of commits belonging\nto one single topic is about doing one single thing, not a random\ncollection.  \"Make sure we always create a merge to record which\nones are from the side branch and which ones are the mainline\" is a\nreasonable way to ensure that.\n\nThe \"the tip being merged into the mainline must always be\nfast-forwardable\", however, is not consistent with the topic branch\nworkflow, and I do not mean this in the sense that you should never\nrebase just before submitting (which is a bad practice).  For an\ninitial merge of the topic to the mainline, the project can keep\nrebasing to the then-current tip of the mainline, and as long as\nthey can afford the cycle to test the result, \"record the range of\nthe topic branch by making a redundant merge\" would work.  \n\nBut that is true only when you have one mainline.  You cannot reuse\nthe topic to maintain an older mainline (i.e. a maintenance track),\nbecause of the \"topic must contain the then-current tip of the\nmainline\" rule.  A topic forked from the tip of master cannot be\nmerged to maint without dragging all the other crap happened since\nmaint to master, and a topic forked from the tip of maint, which can\nbe merged to maint without problem, cannot be merged to master due\nto this \"must contain the tip of master\" rule.\n\nIt gets worse when you need to make a fix-up to the topic.  Has any\nof those who advocate this workflow considered a case where a topic\nlater needs fixups?  Do they always produce a 100% bug-free code so\nthat they do not need to?\n\nIf you have a topic with initially 1 commit, merged to the mainline,\nwith the \"record a redundant merge of fast-forwardable side branch\",\nyou would get this:\n\n\n    ----O---1--- mainline\n         \\ /\n          A      topic\n\n\nwhere the topic only has commit A.  How would you apply a fix this\ncommit?  \"A merged branch must have forked from the then-current tip\"\nwould mean you would do this:\n\n    ----O---1-----2--- mainline\n         \\ / \\   /\n          A   \\ /  topic\n               B   topic-fix\n\ni.e. you cannot touch 'topic' branch, which has 'A', that is sealed\nby the fact that it was already merged to the mainline and the rule\nthat you reject a merge of any side branch that does not fork from\nthe then-current tip.  You are forced to create B forked from the\nmainline to fix A and merge it back to mainline, losing the valuable\n\"these commits, together, achieves this thing\" grouping you wanted\nto achieve with the topic-branch workflow, which is what \"--no-ff\"\nis asking.  This is the reason why I doubt the workflow that wants\nto say \"record a merge with a side branch that contains the current\ntip of the mainline\" is not even internally consistent.\n\nSo, I dunno.\n\n\n"},{"id":"378796","messageId":"87sgrdf91j.fsf@osv.gnss.ru","threadId":"51452","inReplyTo":"xmqqtvbtu9uo.fsf@gitster-ct.c.googlers.com","subject":"Re: Unexpected or wrong ff, no-ff and ff-only behaviour","fromName":"Sergey Organov","fromEmail":"sorganov@gmail.com","sentAt":"2019-07-11T05:13:28Z","receivedAt":"2019-07-11T05:13:34Z","isPatch":false,"sender":{"key":"sorganov@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8501568?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n[...]\n\n> The \"the tip being merged into the mainline must always be\n> fast-forwardable\",\n\nIt's rather \"the tip being merged into the mainline must be fast-forwardable the\nfirst time it is merged\".\n\n> however, is not consistent with the topic branch workflow, and I do\n> not mean this in the sense that you should never rebase just before\n> submitting (which is a bad practice). For an initial merge of the\n> topic to the mainline, the project can keep rebasing to the\n> then-current tip of the mainline, and as long as they can afford the\n> cycle to test the result, \"record the range of the topic branch by\n> making a redundant merge\" would work.\n\nYes, that's exactly it, and, as the rule holds for the first topic merge\nonly, the rest of workflow is as usual, no drastic changes.\n\nOverall, it only ensures the first merge of the topic is semantically\nsimpler, nothing more.\n\n-- Sergey\n"},{"id":"378810","messageId":"20190711154636.GJ9224@genre.crustytoothpaste.net","threadId":"51452","inReplyTo":"CAGyf7-FW-_4AbWE735-=7WjZAaTLHOT_QuWOoHKAjOzZCbWhFA@mail.gmail.com","subject":"Re: Unexpected or wrong ff, no-ff and ff-only behaviour","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2019-07-11T15:46:36Z","receivedAt":"2019-07-11T15:46:45Z","isPatch":false,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On 2019-07-09 at 20:51:39, Bryan Turner wrote:\n> I think this is something I've seen come up on the list before[1]\n> (Roland can correct me if I'm wrong). What I've seen asked for before\n> is the ability to pass the combination \"--ff-only --no-ff\" and have\n> that:\n> * Ensure the branch to be merged is fast-forward from the current\n> branch (i.e., to ensure no merge commit is actually necessary), but\n> * Create a redundant merge commit anyway\n> \n> This retains the ancestry (as in, it shows where the branches were\n> merged), but the merge is always effectively a no-op (no risk of\n> unintended interactions, the sort of subtle breakages where the merge\n> succeeds but the code on each \"side\" isn't entirely compatible,\n> resulting in broken compilation and/or tests and/or runtime).\n\nI should point out that this is scriptable using something like the\nfollowing:\n\n  git fetch origin topic && git merge-base --is-ancestor HEAD FETCH_HEAD && \\\n    git merge --no-ff FETCH_HEAD\n\nor, if you're just merging a branch:\n\n  git merge-base --is-ancestor HEAD topic && \\\n    git merge --no-ff topic\n\nWhile I agree it's not as convenient as having this built-in (and I\nunderstand why people want it), it is achievable with an alias without\nmuch difficulty.\n-- \nbrian m. carlson: Houston, Texas, US\nOpenPGP: https://keybase.io/bk2204\n"},{"id":"378829","messageId":"xmqqftncsdv4.fsf@gitster-ct.c.googlers.com","threadId":"51452","inReplyTo":"87sgrdf91j.fsf@osv.gnss.ru","subject":"Re: Unexpected or wrong ff, no-ff and ff-only behaviour","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-07-11T17:03:11Z","receivedAt":"2019-07-11T17:03:24Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Sergey Organov <sorganov@gmail.com> writes:\n\n> Junio C Hamano <gitster@pobox.com> writes:\n>\n> [...]\n>\n>> The \"the tip being merged into the mainline must always be\n>> fast-forwardable\",\n>\n> It's rather \"the tip being merged into the mainline must be fast-forwardable the\n> first time it is merged\".\n>\n>> however, is not consistent with the topic branch workflow, and I do\n>> not mean this in the sense that you should never rebase just before\n>> submitting (which is a bad practice). For an initial merge of the\n>> topic to the mainline, the project can keep rebasing to the\n>> then-current tip of the mainline, and as long as they can afford the\n>> cycle to test the result, \"record the range of the topic branch by\n>> making a redundant merge\" would work.\n>\n> Yes, that's exactly it, and, as the rule holds for the first topic merge\n> only, the rest of workflow is as usual, no drastic changes.\n>\n> Overall, it only ensures the first merge of the topic is semantically\n> simpler, nothing more.\n\nBut then you have to know to say or omit --ff-only if you are\nmergint the topic for the first time.  The second and subsequent\nmerges, your merges won't be \"semantically simple\" at all.\n\nAnd your first \"semantically simple\" merge is likely to be a merge\nbetween the then-current tip, and a topic that has been prepared\nover a few hours (or longer) and has sufficiently been tested, but\nhas gotten rebased immediately before being merged because of this\n\"must fast-forwardable to maintain semantic simplicity\" policy to\ncatch up with the ever-moving-forward tip of the mainline.  The end\nresult of such a \"semantically simpler\" merge is as good as the\n\"freshly rebased, never had sufficient time to verify the result\"\niteration of the topic branch.\n\nHow would such a state that was freshly rebased without chance of\nenough validation be better than merging the \"sufficiently been\ntested in isolation\" state without doing such a rebase?  If your\nanswer is \"but the contributor would test after rebasing and before\ndoing the --ff-only-plus-no-ff merge\", then perhaps the contributor\ncan also test the result of a (trial) merge before it actually gets\nmerged, no?\n\nIf we have a project like this:\n\n        A               topic that is slightly stale\n       /\n  o---F---o---o---X     mainline\n\nM, A', and N should end up with identical trees:\n\n\n        A-----------M   topic that is slightly stale, merged into mainline\n       /           /\n  o---F---o---o---X---N mainline with A' merged\n                   \\ /\n                    A'  mainline with A rebased on top as A'\n\nAnd by forcing to rebase A to A' before merging into the mainline as\nN, compared to advancing mainline from X to M, one major difference\nthe workflow is making is to _lose_ the information that the topic\nwas cooked in the context of an older mainline and did not take what\nhappened since F until X into account.  Rebasing it to A' without\ngiving the result sufficient vetting means you are forcing the\nupdated topic to pretend as if it also took F..X into account,\nmaking it harder to diagnose subtle interactions with A and F..X\nlater that you did not spot when you made A'; merging to create M\ndoes not have such a problem.  As A' and M would have the identical\ntrees, the same bug resulting from such a subtle interactions would\nbe there if A' has such an issue, but at least M is more honest and\nlets us know that A itself predated what happened between F..X.\n\nSo...\n"},{"id":"378883","messageId":"87blxz9xbh.fsf@osv.gnss.ru","threadId":"51452","inReplyTo":"xmqqftncsdv4.fsf@gitster-ct.c.googlers.com","subject":"Re: Unexpected or wrong ff, no-ff and ff-only behaviour","fromName":"Sergey Organov","fromEmail":"sorganov@gmail.com","sentAt":"2019-07-12T13:50:10Z","receivedAt":"2019-07-12T13:50:16Z","isPatch":false,"sender":{"key":"sorganov@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8501568?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Sergey Organov <sorganov@gmail.com> writes:\n>\n>> Junio C Hamano <gitster@pobox.com> writes:\n>>\n>> [...]\n>>\n>>> The \"the tip being merged into the mainline must always be\n>>> fast-forwardable\",\n>>\n>> It's rather \"the tip being merged into the mainline must be fast-forwardable the\n>> first time it is merged\".\n>>\n>>> however, is not consistent with the topic branch workflow, and I do\n>>> not mean this in the sense that you should never rebase just before\n>>> submitting (which is a bad practice). For an initial merge of the\n>>> topic to the mainline, the project can keep rebasing to the\n>>> then-current tip of the mainline, and as long as they can afford the\n>>> cycle to test the result, \"record the range of the topic branch by\n>>> making a redundant merge\" would work.\n>>\n>> Yes, that's exactly it, and, as the rule holds for the first topic merge\n>> only, the rest of workflow is as usual, no drastic changes.\n>>\n>> Overall, it only ensures the first merge of the topic is semantically\n>> simpler, nothing more.\n>\n> But then you have to know to say or omit --ff-only if you are\n> mergint the topic for the first time.  The second and subsequent\n> merges, your merges won't be \"semantically simple\" at all.\n\nYes, the second and the rest (if any) won't differ, but having the first\none, that supposedly introduces most of changes, \"semantically simple\"\nis still an advantage.\n\n>\n> And your first \"semantically simple\" merge is likely to be a merge\n> between the then-current tip, and a topic that has been prepared\n> over a few hours (or longer) and has sufficiently been tested, but\n> has gotten rebased immediately before being merged because of this\n> \"must fast-forwardable to maintain semantic simplicity\" policy to\n> catch up with the ever-moving-forward tip of the mainline.  The end\n> result of such a \"semantically simpler\" merge is as good as the\n> \"freshly rebased, never had sufficient time to verify the result\"\n> iteration of the topic branch.\n\nYes, this makes sense only in otherwise rebase-based workflows, when you\ndo rebase anyway.\n\n> How would such a state that was freshly rebased without chance of\n> enough validation be better than merging the \"sufficiently been\n> tested in isolation\" state without doing such a rebase?  If your\n> answer is \"but the contributor would test after rebasing and before\n> doing the --ff-only-plus-no-ff merge\", then perhaps the contributor\n> can also test the result of a (trial) merge before it actually gets\n> merged, no?\n\nYes, I mean a workflow where testing of rebased (or merged, doesn't\nmatter, as they should actually be the same thing) version is possible\nor even required, and I believe that in this particular case testing\nrebased version and merging the result makes more sense, see below.\n\n>\n> If we have a project like this:\n>\n>         A               topic that is slightly stale\n>        /\n>   o---F---o---o---X     mainline\n>\n> M, A', and N should end up with identical trees:\n>\n>\n>         A-----------M   topic that is slightly stale, merged into mainline\n>        /           /\n>   o---F---o---o---X---N mainline with A' merged\n>                    \\ /\n>                     A'  mainline with A rebased on top as A'\n>\n> And by forcing to rebase A to A' before merging into the mainline as\n> N, compared to advancing mainline from X to M, one major difference\n> the workflow is making is to _lose_ the information that the topic\n> was cooked in the context of an older mainline and did not take what\n> happened since F until X into account.  Rebasing it to A' without\n> giving the result sufficient vetting means you are forcing the\n> updated topic to pretend as if it also took F..X into account,\n> making it harder to diagnose subtle interactions with A and F..X\n> later that you did not spot when you made A'; merging to create M\n> does not have such a problem.  As A' and M would have the identical\n> trees, the same bug resulting from such a subtle interactions would\n> be there if A' has such an issue, but at least M is more honest and\n> lets us know that A itself predated what happened between F..X.\n>\n> So...\n\nSo it has a disadvantage for the workflow you have in mind, and you\nwon't use the feature should you decide the disadvantage outweighs the\naforementioned advantage, as usual.\n\nHowever, committing untested M still doesn't taste as the best possible\nway of handling things in general. It'd be best to actually test M or N\nbefore publishing. In a workflow where there are measures to do it,\ntesting A' (= N) and publishing N both makes more sense and results in\nsimpler history than merging A and then testing and publishing M.\n\nThat said, even if we rather all do agree rebase workflow is always\ninferior to merge one, is it satisfactory excuse to actively resist\notherwise logical behavior of 'git merge' that is even documented? I\ndon't think so.\n\nThus, one way or another, I'd still vote for keeping options description\nintact, and rather fix the implementation to match the manual, i.e.,\nmake the --[no]-ff actually orthogonal to --ff-only.\n\n-- Sergey\n"},{"id":"378893","messageId":"20190712162450.21898-1-newren@gmail.com","threadId":"51452","inReplyTo":"87blxz9xbh.fsf@osv.gnss.ru","subject":"Re: Unexpected or wrong ff, no-ff and ff-only behaviour","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2019-07-12T16:24:50Z","receivedAt":"2019-07-12T16:24:59Z","isPatch":false,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Fri, Jul 12, 2019 at 6:50 AM Sergey Organov <sorganov@gmail.com> wrote:\n>\n> That said, even if we rather all do agree rebase workflow is always\n> inferior to merge one, is it satisfactory excuse to actively resist\n> otherwise logical behavior of 'git merge' that is even documented? I\n> don't think so.\n>\n> Thus, one way or another, I'd still vote for keeping options description\n> intact, and rather fix the implementation to match the manual, i.e.,\n> make the --[no]-ff actually orthogonal to --ff-only.\n\nThis seems like it's asking for trouble.  --ff-only and --no-ff,\nignoring any knowledge of what they do, are contradictory by their\nnames.  Attempting to explain to users that they are not opposites but\ncan be used together compatibly sounds very problematic to me.\n\nBut let me dig a little deeper into your statement of \"resisting\notherwise logical behavior of 'git merge\" that is even documented.\"\nGoing back to when the --ff-only option was introduced:\n\ncommit 134748353b2a71a34f899c9b1326ccf7ae082412\nAuthor: Björn Gustavsson <bgustavsson@gmail.com>\nDate:   Thu Oct 29 23:08:31 2009 +0100\n\n    Teach 'git merge' and 'git pull' the option --ff-only\n   \n    For convenience in scripts and aliases, add the option\n    --ff-only to only allow fast-forwards (and up-to-date,\n    despite the name).\n   \n    Disallow combining --ff-only and --no-ff, since they\n    flatly contradict each other.\n\nWe see that the original author even stated pretty clearly and\nstrongly that these were polar opposite options.  Our description\ntoday of --ff-only is the same one he introduced in that patch, and I\nalways read the description the same way I think he did: that it\nimplied a polar opposite of --no-ff.  You and Bryan came along and\npointed out that the description was actually ambiguous and could be\ninterpreted a different way...and I then had to re-read the text a\ntime or two after you pointed it out to see the alternate reading.  I\ntotally admit that the wording is apparently ambiguous and can be read\nthe way you have, but I don't at all see that as a reason to keep the\ndocumentation as-is.  Either it should be clarified to rule out what\nyou and usbuser wanted and perhaps misunderstood it to do, or if the\nbehavior is changed then it should be clarified so that folks like me\ndon't read it to behave as it has since Björn added it.\n\nPersonally, I think that if new functionality is wanted, it should\ndefinitely go in a different flag (perhaps someone can find something\nshorter than --no-ff-and-only-if-ff-is-possible).  But I think Junio\nmakes a pretty good argument to be leery of such a new option, and\nBrian points out how to easily get this behavior by just stringing\ntogether a merge-base command with merge --no-ff.\n\nThat's just my $0.02, but since this is the second time in the thread\nthat I've suggested improving the documentation, here's a patch to do\nso:\n\n\n-- 8< --\nSubject: [PATCH] merge-options.txt: clarify meaning of various ff-related\n options\n\nAs discovered on the mailing list, some of the descriptions of the\nff-related options were unclear.  Try to be more precise with what these\noptions do.\n\nSigned-off-by: Elijah Newren <newren@gmail.com>\n---\n Documentation/merge-options.txt | 21 +++++++++++----------\n 1 file changed, 11 insertions(+), 10 deletions(-)\n\ndiff --git a/Documentation/merge-options.txt b/Documentation/merge-options.txt\nindex 79a00d2a4a..e888c99d48 100644\n--- a/Documentation/merge-options.txt\n+++ b/Documentation/merge-options.txt\n@@ -40,20 +40,21 @@ set to `no` at the beginning of them.\n \tcase of a merge conflict.\n \n --ff::\n-\tWhen the merge resolves as a fast-forward, only update the branch\n-\tpointer, without creating a merge commit.  This is the default\n-\tbehavior.\n+\tWhen the merge resolves as a fast-forward, only update the\n+\tbranch pointer (without creating a merge commit).  When a fast\n+\tforward update is not possible, create a merge commit.  This is\n+\tthe default behavior.\n \n --no-ff::\n-\tCreate a merge commit even when the merge resolves as a\n-\tfast-forward.  This is the default behaviour when merging an\n-\tannotated (and possibly signed) tag that is not stored in\n-\tits natural place in 'refs/tags/' hierarchy.\n+\tCreate a merge commit even when the merge could instead resolve\n+\tas a fast-forward.  This is the default behaviour when merging\n+\tan annotated (and possibly signed) tag that is not stored in its\n+\tnatural place in 'refs/tags/' hierarchy.\n \n --ff-only::\n-\tRefuse to merge and exit with a non-zero status unless the\n-\tcurrent `HEAD` is already up to date or the merge can be\n-\tresolved as a fast-forward.\n+\tWhen possible, resolve the merge as a fast-forward (do not\n+\tcreate a merge commit).  When not possible, refuse to merge and\n+\texit with a non-zero status.\n \n -S[<keyid>]::\n --gpg-sign[=<keyid>]::\n-- \n2.22.0.429.gbb0a79e5f4\n\n"},{"id":"378900","messageId":"xmqqh87rp0gy.fsf@gitster-ct.c.googlers.com","threadId":"51452","inReplyTo":"87blxz9xbh.fsf@osv.gnss.ru","subject":"Re: Unexpected or wrong ff, no-ff and ff-only behaviour","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-07-12T18:33:01Z","receivedAt":"2019-07-12T18:33:13Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Sergey Organov <sorganov@gmail.com> writes:\n\n>> If we have a project like this:\n>>\n>>         A               topic that is slightly stale\n>>        /\n>>   o---F---o---o---X     mainline\n>>\n>> M, A', and N should end up with identical trees:\n>>\n>>\n>>         A-----------M   topic that is slightly stale, merged into mainline\n>>        /           /\n>>   o---F---o---o---X---N mainline with A' merged\n>>                    \\ /\n>>                     A'  mainline with A rebased on top as A'\n>>\n>> And by forcing to rebase A to A' before merging into the mainline as\n>> N, compared to advancing mainline from X to M, one major difference\n>> the workflow is making is to _lose_ the information that the topic\n>> was cooked in the context of an older mainline and did not take what\n>> happened since F until X into account....\n>\n> However, committing untested M still doesn't taste as the best possible\n> way of handling things in general. It'd be best to actually test M or N\n> before publishing.\n\nOh, no question about it.  I am not advocating (and I do not do\npersonally) publishing an untested tip.  \n\nBut the point is, if M and N are equally well tested before\npublication, they may still have bugs resulting from subtle\ninteractions between A and F..X that is not discovered during that\ntesting.  And N loses the information that would help diagnosing\nwhat went wrong, which does not happen if you published M.\n\nAbout the docs easily getting misinterpreted, I think Elijah covered\nit pretty well.\n\nThanks.\n"},{"id":"378938","messageId":"87zhlfzejb.fsf@osv.gnss.ru","threadId":"51452","inReplyTo":"20190712162450.21898-1-newren@gmail.com","subject":"Re: Unexpected or wrong ff, no-ff and ff-only behaviour","fromName":"Sergey Organov","fromEmail":"sorganov@gmail.com","sentAt":"2019-07-15T12:08:08Z","receivedAt":"2019-07-15T12:08:15Z","isPatch":false,"sender":{"key":"sorganov@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8501568?v=4"},"body":"Elijah Newren <newren@gmail.com> writes:\n\n> On Fri, Jul 12, 2019 at 6:50 AM Sergey Organov <sorganov@gmail.com> wrote:\n>>\n>> That said, even if we rather all do agree rebase workflow is always\n>> inferior to merge one, is it satisfactory excuse to actively resist\n>> otherwise logical behavior of 'git merge' that is even documented? I\n>> don't think so.\n>>\n>> Thus, one way or another, I'd still vote for keeping options description\n>> intact, and rather fix the implementation to match the manual, i.e.,\n>> make the --[no]-ff actually orthogonal to --ff-only.\n>\n> This seems like it's asking for trouble.  --ff-only and --no-ff,\n> ignoring any knowledge of what they do, are contradictory by their\n> names.\n\nI agree --ff-only is not the best name for what I have in mind. However,\nit's not the best name for actual behavior either, as for this case\n[--ff|--no-ff|--only-ff], or even '--ff=[prefer|never|only]' would look\nmore consistent.\n\n> Attempting to explain to users that they are not opposites but\n> can be used together compatibly sounds very problematic to me.\n\nFor me current documentation would be clear enough, provided the options\nwould indeed behave the way they are described. Unfortunately (for me),\nthey don't behave that way, and it looks like they never will.\n\n> But let me dig a little deeper into your statement of \"resisting\n> otherwise logical behavior of 'git merge\" that is even documented.\"\n> Going back to when the --ff-only option was introduced:\n>\n> commit 134748353b2a71a34f899c9b1326ccf7ae082412\n> Author: Björn Gustavsson <bgustavsson@gmail.com>\n> Date:   Thu Oct 29 23:08:31 2009 +0100\n>\n>     Teach 'git merge' and 'git pull' the option --ff-only\n>\n>     For convenience in scripts and aliases, add the option\n>     --ff-only to only allow fast-forwards (and up-to-date,\n>     despite the name).\n>\n>     Disallow combining --ff-only and --no-ff, since they\n>     flatly contradict each other.\n>\n> We see that the original author even stated pretty clearly and\n> strongly that these were polar opposite options.  Our description\n> today of --ff-only is the same one he introduced in that patch, and I\n> always read the description the same way I think he did: that it\n> implied a polar opposite of --no-ff.\n\nOK, so it was at the very beginning where opportunity for better design\nhas been missed.\n\n> You and Bryan came along and\n> pointed out that the description was actually ambiguous and could be\n> interpreted a different way...and I then had to re-read the text a\n> time or two after you pointed it out to see the alternate reading.  I\n> totally admit that the wording is apparently ambiguous and can be read\n> the way you have, but I don't at all see that as a reason to keep the\n> documentation as-is.  Either it should be clarified to rule out what\n> you and usbuser wanted and perhaps misunderstood it to do, or if the\n> behavior is changed then it should be clarified so that folks like me\n> don't read it to behave as it has since Björn added it.\n>\n> Personally, I think that if new functionality is wanted, it should\n> definitely go in a different flag (perhaps someone can find something\n> shorter than --no-ff-and-only-if-ff-is-possible).  But I think Junio\n> makes a pretty good argument to be leery of such a new option, and\n> Brian points out how to easily get this behavior by just stringing\n> together a merge-base command with merge --no-ff.\n\nMy argument was *not* that we absolutely must have this functionality,\nit was rather that if we had made '--ff-only' option orthogonal (that is\na good thing in general by itself), this functionality would come almost\nfor free. No documentation change then. However, now I see that such\nchange at this point will change behavior of certain combinations of\noptions in incompatible manner, and so is not a good way to go.\n\nBTW, I did suggest a new option for this functionality once, Junio being\nin opposition then as well, arguing that it looks like adding a feature\njust for the sake of having a feature. At that time I found 'git merge'\nhappily takes both '--no-ff --ff-only', and made a mistake of assuming,\nafter re-reading the manual, that it in fact does what is documented, so\nI dropped the issue of adding a new option then.\n\n> That's just my $0.02, but since this is the second time in the thread\n> that I've suggested improving the documentation, here's a patch to do\n> so:\n>\n> -- 8< --\n> Subject: [PATCH] merge-options.txt: clarify meaning of various ff-related\n>  options\n>\n> As discovered on the mailing list, some of the descriptions of the\n> ff-related options were unclear.  Try to be more precise with what these\n> options do.\n>\n> Signed-off-by: Elijah Newren <newren@gmail.com>\n> ---\n>  Documentation/merge-options.txt | 21 +++++++++++----------\n>  1 file changed, 11 insertions(+), 10 deletions(-)\n>\n> diff --git a/Documentation/merge-options.txt b/Documentation/merge-options.txt\n> index 79a00d2a4a..e888c99d48 100644\n> --- a/Documentation/merge-options.txt\n> +++ b/Documentation/merge-options.txt\n> @@ -40,20 +40,21 @@ set to `no` at the beginning of them.\n>  \tcase of a merge conflict.\n>\n>  --ff::\n> -\tWhen the merge resolves as a fast-forward, only update the branch\n> -\tpointer, without creating a merge commit.  This is the default\n> -\tbehavior.\n> +\tWhen the merge resolves as a fast-forward, only update the\n> +\tbranch pointer (without creating a merge commit).  When a fast\n> +\tforward update is not possible, create a merge commit.  This is\n> +\tthe default behavior.\n\nA side note: except it is *not* the default \"when merging an\nannotated...\", described below.\n\n>\n>  --no-ff::\n> -\tCreate a merge commit even when the merge resolves as a\n> -\tfast-forward.  This is the default behaviour when merging an\n> -\tannotated (and possibly signed) tag that is not stored in\n> -\tits natural place in 'refs/tags/' hierarchy.\n> +\tCreate a merge commit even when the merge could instead resolve\n> +\tas a fast-forward.  This is the default behaviour when merging\n> +\tan annotated (and possibly signed) tag that is not stored in its\n> +\tnatural place in 'refs/tags/' hierarchy.\n>\n>  --ff-only::\n> -\tRefuse to merge and exit with a non-zero status unless the\n> -\tcurrent `HEAD` is already up to date or the merge can be\n> -\tresolved as a fast-forward.\n> +\tWhen possible, resolve the merge as a fast-forward (do not\n> +\tcreate a merge commit).  When not possible, refuse to merge and\n> +\texit with a non-zero status.\n\nYeah, this resolves uncertainty.\n\nHowever, I think it'd be better to format it after other similar cases,\nto make it explicit these options are 3-way choice. I mean something\nlike this:\n\n--ff::\n--no-ff::\n--ff-only::\n\tWhen the merge resolves as a fast-forward, only update the\n\tbranch pointer (without creating a merge commit).  When a fast\n\tforward update is not possible, create a merge commit.  This is\n\tthe default behavior, unless merging an annotated (and possibly\n\tsigned) tag that is not stored in its natural place in\n\t'refs/tags/' hierarchy, in which case --no-ff is assumed.\n+\nWith --no-ff create a merge commit even when the merge could instead\nresolve as a fast-forward.\n+\nWith --ff-only resolve the merge as a fast-forward (never create a merge\ncommit). When fast-forward is not possible, refuse to merge and exit\nwith non-zero status.\n\n\n-- Sergey\n"},{"id":"378943","messageId":"874l3nzcpo.fsf@osv.gnss.ru","threadId":"51452","inReplyTo":"xmqqh87rp0gy.fsf@gitster-ct.c.googlers.com","subject":"Re: Unexpected or wrong ff, no-ff and ff-only behaviour","fromName":"Sergey Organov","fromEmail":"sorganov@gmail.com","sentAt":"2019-07-15T12:47:31Z","receivedAt":"2019-07-15T12:47:39Z","isPatch":false,"sender":{"key":"sorganov@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8501568?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Sergey Organov <sorganov@gmail.com> writes:\n>\n>>> If we have a project like this:\n>>>\n>>>         A               topic that is slightly stale\n>>>        /\n>>>   o---F---o---o---X     mainline\n>>>\n>>> M, A', and N should end up with identical trees:\n>>>\n>>>\n>>>         A-----------M   topic that is slightly stale, merged into mainline\n>>>        /           /\n>>>   o---F---o---o---X---N mainline with A' merged\n>>>                    \\ /\n>>>                     A'  mainline with A rebased on top as A'\n>>>\n>>> And by forcing to rebase A to A' before merging into the mainline as\n>>> N, compared to advancing mainline from X to M, one major difference\n>>> the workflow is making is to _lose_ the information that the topic\n>>> was cooked in the context of an older mainline and did not take what\n>>> happened since F until X into account....\n>>\n>> However, committing untested M still doesn't taste as the best possible\n>> way of handling things in general. It'd be best to actually test M or N\n>> before publishing.\n>\n> Oh, no question about it.  I am not advocating (and I do not do\n> personally) publishing an untested tip.  \n>\n> But the point is, if M and N are equally well tested before\n> publication, they may still have bugs resulting from subtle\n> interactions between A and F..X that is not discovered during that\n> testing.  And N loses the information that would help diagnosing\n> what went wrong, which does not happen if you published M.\n\nI see your point.\n\nMy point is that it's still a /choice/ between more information and\nhistory simplification. It's not one way. I dispute that keeping\nreference to the original branch has enough significance to /always/\noverweight opportunity for history simplification, no matter what\nworkflow is in use.\n\n> About the docs easily getting misinterpreted, I think Elijah covered\n> it pretty well.\n\nYeah, sure, the docs should better be fixed.\n\nAnyway, bare \"git --no-ff\" is still there, and I can live with no safety\nbelt that '--ff-only' could easily have been, it's just that it's a pity\nto see lost opportunities in the design.\n\nThanks,\n\n-- Sergey\n"},{"id":"378946","messageId":"xmqqtvbn44mx.fsf@gitster-ct.c.googlers.com","threadId":"51452","inReplyTo":"874l3nzcpo.fsf@osv.gnss.ru","subject":"Re: Unexpected or wrong ff, no-ff and ff-only behaviour","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-07-15T16:57:42Z","receivedAt":"2019-07-15T16:57:51Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Sergey Organov <sorganov@gmail.com> writes:\n\n> Junio C Hamano <gitster@pobox.com> writes:\n>\n>> Sergey Organov <sorganov@gmail.com> writes:\n>>\n>> But the point is, if M and N are equally well tested before\n>> publication, they may still have bugs resulting from subtle\n>> interactions between A and F..X that is not discovered during that\n>> testing.  And N loses the information that would help diagnosing\n>> what went wrong, which does not happen if you published M.\n>\n> I see your point.\n>\n> My point is that it's still a /choice/ between more information and\n> history simplification.\n\nI actually fail to see that point.\n\nIf we are not constrained by that \"first merge of a topic must be a\nredundant fast-forward merge\", a topic that originally had two\ncommits A and B, merged to the mainline to produce M and then\nfurther corrected with a commit C before it gets merged back at O to\nthe mainline would leave this history:\n\n          A-----------B-------C\n         /             \\       \\\n    o---F---o---o---X---M---o---O---\n\nIf you enforce the \"first merge of a topic must be a redundant\nfast-forward merge\" rule, you'd end up with a history like this:\n\n          A-----------B\n         /\n    o---F---o---o---X-------N---o---P---\n                     \\     /       /\n                      A'--B'------C\n\nIs the latter materially simpler than the former?  I do not think\nso.\n\nI was preparing myself to say \"we rejected the combination because\nit would encourage wrong workflow, but perhaps over the years people\nlike you and usbuser may have found good use patterns different from\nwhat we considered back then, and these use patterns may not\nencourage wrong workflows.  It may not be a bad idea to introduce a\nnew optional behaviour if that is the case\", but what I heard so far\ndoes not convince me that we have good use patterns.\n>> About the docs easily getting misinterpreted, I think Elijah covered\n>> it pretty well.\n>\n> Yeah, sure, the docs should better be fixed.\n>\n> Anyway, bare \"git --no-ff\" is still there, and I can live with no safety\n> belt that '--ff-only' could easily have been, it's just that it's a pity\n> to see lost opportunities in the design.\n\nLost opportunities to add an option to encourage bad workflow?  \n\nNo, thanks ;-)\n\nBut thanks for a discussion anyway.\n\n"},{"id":"379095","messageId":"87r26me1bb.fsf@osv.gnss.ru","threadId":"51452","inReplyTo":"xmqqtvbn44mx.fsf@gitster-ct.c.googlers.com","subject":"Re: Unexpected or wrong ff, no-ff and ff-only behaviour","fromName":"Sergey Organov","fromEmail":"sorganov@gmail.com","sentAt":"2019-07-19T11:00:40Z","receivedAt":"2019-07-19T11:00:50Z","isPatch":false,"sender":{"key":"sorganov@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8501568?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Sergey Organov <sorganov@gmail.com> writes:\n>\n>> Junio C Hamano <gitster@pobox.com> writes:\n>>\n>>> Sergey Organov <sorganov@gmail.com> writes:\n>>>\n>>> But the point is, if M and N are equally well tested before\n>>> publication, they may still have bugs resulting from subtle\n>>> interactions between A and F..X that is not discovered during that\n>>> testing.  And N loses the information that would help diagnosing\n>>> what went wrong, which does not happen if you published M.\n>>\n>> I see your point.\n>>\n>> My point is that it's still a /choice/ between more information and\n>> history simplification.\n>\n> I actually fail to see that point.\n\nI'm sorry you do. Let me try again.\n\n>\n> If we are not constrained by that \"first merge of a topic must be a\n> redundant fast-forward merge\", a topic that originally had two\n> commits A and B, merged to the mainline to produce M and then\n> further corrected with a commit C before it gets merged back at O to\n> the mainline would leave this history:\n>\n>           A-----------B-------C\n>          /             \\       \\\n>     o---F---o---o---X---M---o---O---\n>\n> If you enforce the \"first merge of a topic must be a redundant\n> fast-forward merge\" rule, you'd end up with a history like this:\n>\n>           A-----------B\n>          /\n>     o---F---o---o---X-------N---o---P---\n>                      \\     /       /\n>                       A'--B'------C\n>\n> Is the latter materially simpler than the former?  I do not think\n> so.\n\nI think it is. To see it clearly, let's cut common parts, and then cut\nirrelevant parts as well from the pictures you gave:\n\n           A-----------B\n          /             \\\n     o---F---o---o---X---M\n\n                  ---X-------N---\n                      \\     /\n                       A'--B'\n\nThere is both qualitative and quantitative difference here.\n\n1. The qualitative difference.\n\nIn the former case we have outdated topic branch and a merge commit that\nsimultaneously serves two purposes: gives a recipe to bring outdated\nbranch up to date, and records the fact that the topic in now merged to\nmainline.\n\nIn the letter case we have up to date topic branch and a merge commit\nthat servers exactly one one purpose: it records the fact that the topic\nin now merged to mainline.\n\nThis is exactly the \"material\" part of the simplification I mean.\n\n2. The quantitative difference.\n\nIn the latter case the horizon to reason about the topic branch and its\nadoption to mainline is at commit X, while in the former case it is at\ncommit F.\n\nThe quantitative difference that we have here is proportional to the\nsize of diff between X and F, and once we aim at decreasing this\ndifference (i.e., not accepting very outdated branches), it's only\nlogical to get rid of this difference entirely, once again ending up\nwith the latter case.\n\nFinally, please also notice that ability to reference outdated version\nof the topic branch (or even multiple of them), provided there is actual\nreason to, is still there:\n\n$ git checkout topic\n$ git pull --rebase\n$ git merge -s ours topic@{1} # keep reference to original\n$ git checkout mainline\n$ git merge --no-ff topic\n\n> I was preparing myself to say \"we rejected the combination because\n> it would encourage wrong workflow, but perhaps over the years people\n> like you and usbuser may have found good use patterns different from\n> what we considered back then, and these use patterns may not\n> encourage wrong workflows.  It may not be a bad idea to introduce a\n> new optional behaviour if that is the case\", but what I heard so far\n> does not convince me that we have good use patterns.\n>\n>>> About the docs easily getting misinterpreted, I think Elijah covered\n>>> it pretty well.\n>>\n>> Yeah, sure, the docs should better be fixed.\n>>\n>> Anyway, bare \"git --no-ff\" is still there, and I can live with no safety\n>> belt that '--ff-only' could easily have been, it's just that it's a pity\n>> to see lost opportunities in the design.\n>\n> Lost opportunities to add an option to encourage bad workflow?  \n>\n> No, thanks ;-)\n\nI dunno what is that \"bad workflow\" you have in mind, sorry.\n\n-- Sergey\n"}]}