{"thread":{"id":"53726","subject":"Request for adding a simple mechanism to exclude files from Git merge operation","startedAt":"2020-06-20T18:21:47Z","lastAt":"2020-06-25T11:47:00Z","messageCount":16,"participants":["Tiran Meltser","Philip Oakley","brian m. carlson","Sergey Organov","Elijah Newren","Junio C Hamano","Chris Torek"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"400259","messageId":"DM6PR11MB27958B80E3994CEEF13971ECE5990@DM6PR11MB2795.namprd11.prod.outlook.com","threadId":"53726","inReplyTo":null,"subject":"Request for adding a simple mechanism to exclude files from Git merge operation","fromName":"Tiran Meltser","fromEmail":"tiran.meltser@mavenir.com","sentAt":"2020-06-20T18:21:40Z","receivedAt":"2020-06-20T18:21:47Z","isPatch":false,"sender":{"key":"tiran.meltser@mavenir.com","avatar":null},"body":"Hi,\nThis topic is quite common in various use cases (e.g. production configuration vs. staging one) and there are quite a few talks about it in the web.\nNevertheless, there is no specific solution to this problem, only partial workarounds (including the famous merge driver “ours”).\n\nI would like to suggest adding the git a simple and precise handling for the need to mark file(s)/folder(s) that are branch specific and should not be involved in merge operation at all.\n\n2 suggestions I can think of are (but any good solution would suffice):\n• Adding additional merge strategy indication the file/folder is excluded from merges (e.g. merge=disabled/none/skip/…)\n• Adding a new configuration file (like .gitignore) for tracking these special files/folders, for example: .gitisolate/.gitquarantine/.gitbranchspecific/.gitsilo/…\n\nAny comment would be appreciated.\n\n10x,\nTiran Meltser\n________________________________\nThis e-mail message may contain confidential or proprietary information of Mavenir Systems, Inc. or its affiliates and is intended solely for the use of the intended recipient(s). If you are not the intended recipient of this message, you are hereby notified that any review, use or distribution of this information is absolutely prohibited and we request that you delete all copies in your control and contact us by e-mailing to security@mavenir.com. This message contains the views of its author and may not necessarily reflect the views of Mavenir Systems, Inc. or its affiliates, who employ systems to monitor email messages, but make no representation that such messages are authorized, secure, uncompromised, or free from computer viruses, malware, or other defects. Thank You\n"},{"id":"400267","messageId":"e9534404-7c2c-bec0-465e-7c0149734e3a@iee.email","threadId":"53726","inReplyTo":"DM6PR11MB27958B80E3994CEEF13971ECE5990@DM6PR11MB2795.namprd11.prod.outlook.com","subject":"Re: Request for adding a simple mechanism to exclude files from Git merge operation","fromName":"Philip Oakley","fromEmail":"philipoakley@iee.email","sentAt":"2020-06-21T15:43:15Z","receivedAt":"2020-06-21T15:43:19Z","isPatch":false,"sender":{"key":"philipoakley@iee.email","avatar":"https://avatars.githubusercontent.com/u/914343?v=4"},"body":"On 20/06/2020 19:21, Tiran Meltser wrote:\n> Hi,\n> This topic is quite common in various use cases (e.g. production configuration vs. staging one) and there are quite a few talks about it in the web.\n> Nevertheless, there is no specific solution to this problem, only partial workarounds (including the famous merge driver “ours”).\n>\n> I would like to suggest adding the git a simple and precise handling for the need to mark file(s)/folder(s) that are branch specific and should not be involved in merge operation at all.\n>\n> 2 suggestions I can think of are (but any good solution would suffice):\n> • Adding additional merge strategy indication the file/folder is excluded from merges (e.g. merge=disabled/none/skip/…)\n> • Adding a new configuration file (like .gitignore) for tracking these special files/folders, for example: .gitisolate/.gitquarantine/.gitbranchspecific/.gitsilo/…\n>\n> Any comment would be appreciated.\n>\n>\nThere has been a lot of previous discussion on \"precious\" files in the\npast, but without any solid solution.\n(https://lore.kernel.org/git/?q=precious+file to start).\n\n\nThere is a current thread on progressive merge resolution, where not all\nconflicts can be resolved by one person at one time, which may also be\nof interest.\nhttps://public-inbox.org/git/BY5PR19MB3400DC6B6065C1FFF2ED289890990@BY5PR19MB3400.namprd19.prod.outlook.com/T/#m56b34554612b44be17e61da6486c1f709c2cfe54\n\nPhilip\n"},{"id":"400306","messageId":"DM6PR11MB2795F789FD7011DCF0D3D5C5E5970@DM6PR11MB2795.namprd11.prod.outlook.com","threadId":"53726","inReplyTo":"e9534404-7c2c-bec0-465e-7c0149734e3a@iee.email","subject":"RE: [E] Re: Request for adding a simple mechanism to exclude files from Git merge operation","fromName":"Tiran Meltser","fromEmail":"tiran.meltser@mavenir.com","sentAt":"2020-06-22T18:42:59Z","receivedAt":"2020-06-22T18:43:06Z","isPatch":false,"sender":{"key":"tiran.meltser@mavenir.com","avatar":null},"body":"Hi Philip,\nFirst - thanks for taking the time to comment on the issue.\nSecond - as for the \"precious\" file, not sure this is my case; it could go there, but as you indicated it has been around for some time without progressing anywhere.\nThird - the last link you sent doesn't seem to be related to my issue as it deals with complex merges, while my request is very simple - give the ability to mark files/folders as omitted from a merge operation (branch specific files).\n\nIMHO this feature isn't complicated and can bring lots of benefits to the table.\n\nHope someone will take up the glove...\n\nTiran.\n-----Original Message-----\nFrom: Philip Oakley <philipoakley@iee.email>\nSent: Sunday, June 21, 2020 6:43 PM\nTo: Tiran Meltser <Tiran.Meltser@mavenir.com>; git@vger.kernel.org\nCc: Amir Yosef <Amir.Yosef@mavenir.com>\nSubject: [E] Re: Request for adding a simple mechanism to exclude files from Git merge operation\n\n[EXTERNAL EMAIL] DO NOT CLICK links or attachments unless you recognize the sender and know the content is safe.\n\nOn 20/06/2020 19:21, Tiran Meltser wrote:\n> Hi,\n> This topic is quite common in various use cases (e.g. production configuration vs. staging one) and there are quite a few talks about it in the web.\n> Nevertheless, there is no specific solution to this problem, only partial workarounds (including the famous merge driver “ours”).\n>\n> I would like to suggest adding the git a simple and precise handling for the need to mark file(s)/folder(s) that are branch specific and should not be involved in merge operation at all.\n>\n> 2 suggestions I can think of are (but any good solution would suffice):\n> • Adding additional merge strategy indication the file/folder is\n> excluded from merges (e.g. merge=disabled/none/skip/…) • Adding a new\n> configuration file (like .gitignore) for tracking these special\n> files/folders, for example:\n> .gitisolate/.gitquarantine/.gitbranchspecific/.gitsilo/…\n>\n> Any comment would be appreciated.\n>\n>\nThere has been a lot of previous discussion on \"precious\" files in the past, but without any solid solution.\n(https://lore.kernel.org/git/?q=precious+file to start).\n\n\nThere is a current thread on progressive merge resolution, where not all conflicts can be resolved by one person at one time, which may also be of interest.\nhttps://public-inbox.org/git/BY5PR19MB3400DC6B6065C1FFF2ED289890990@BY5PR19MB3400.namprd19.prod.outlook.com/T/#m56b34554612b44be17e61da6486c1f709c2cfe54\n\nPhilip\n________________________________\nThis e-mail message may contain confidential or proprietary information of Mavenir Systems, Inc. or its affiliates and is intended solely for the use of the intended recipient(s). If you are not the intended recipient of this message, you are hereby notified that any review, use or distribution of this information is absolutely prohibited and we request that you delete all copies in your control and contact us by e-mailing to security@mavenir.com. This message contains the views of its author and may not necessarily reflect the views of Mavenir Systems, Inc. or its affiliates, who employ systems to monitor email messages, but make no representation that such messages are authorized, secure, uncompromised, or free from computer viruses, malware, or other defects. Thank You\n"},{"id":"400308","messageId":"20200622194122.GN6531@camp.crustytoothpaste.net","threadId":"53726","inReplyTo":"DM6PR11MB27958B80E3994CEEF13971ECE5990@DM6PR11MB2795.namprd11.prod.outlook.com","subject":"Re: Request for adding a simple mechanism to exclude files from Git merge operation","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2020-06-22T19:41:22Z","receivedAt":"2020-06-22T19:41:31Z","isPatch":false,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On 2020-06-20 at 18:21:40, Tiran Meltser wrote:\n> Hi,\n> This topic is quite common in various use cases (e.g. production configuration vs. staging one) and there are quite a few talks about it in the web.\n> Nevertheless, there is no specific solution to this problem, only partial workarounds (including the famous merge driver “ours”).\n\nIn general, this is a hard problem.  When you perform a merge, you're\nasking to incorporate changes from both heads against a common merge\nbase.  What does it mean when you want to merge two branches together\nbut not make any changes?  Which version do you want, ours or theirs?\nNormally merges are symmetric, so if you want non-symmetric behavior,\nyou have to define what it's supposed to be.\n\nIn addition, it's probably not the case that you want _never_ to modify\nthe contents of a file on a merge.  For example, if you have a feature\nbranch to update the production configuration to fix an issue or add a\nnew option, you probably do very much want that merge to succeed and not\nbe a no-op, so a configuration in .gitattributes may not be helpful for\nyour use case.\n\nBecause this is such a tricky problem and there usually isn't a\nconsistent set of behavior that people _always_ want to apply (unlike,\nsay, line endings), the general recommendation here is that folks just\navoid this problem altogether.  For example, your repository can contain\nconfigs for development, production, and staging and a script can copy\nthe appropriate one into place based on an environment variable or\nhostname.\n-- \nbrian m. carlson: Houston, Texas, US\nOpenPGP: https://keybase.io/bk2204\n"},{"id":"400359","messageId":"871rm6x86y.fsf@osv.gnss.ru","threadId":"53726","inReplyTo":"20200622194122.GN6531@camp.crustytoothpaste.net","subject":"Re: Request for adding a simple mechanism to exclude files from Git merge operation","fromName":"Sergey Organov","fromEmail":"sorganov@gmail.com","sentAt":"2020-06-23T12:44:53Z","receivedAt":"2020-06-23T12:44:58Z","isPatch":false,"sender":{"key":"sorganov@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8501568?v=4"},"body":"\"brian m. carlson\" <sandals@crustytoothpaste.net> writes:\n\n> On 2020-06-20 at 18:21:40, Tiran Meltser wrote:\n>> Hi,\n>> This topic is quite common in various use cases (e.g. production\n>> configuration vs. staging one) and there are quite a few talks about\n>> it in the web.\n>> Nevertheless, there is no specific solution to this problem, only\n>> partial workarounds (including the famous merge driver “ours”).\n>\n> In general, this is a hard problem.  When you perform a merge, you're\n> asking to incorporate changes from both heads against a common merge\n> base.  What does it mean when you want to merge two branches together\n> but not make any changes?  Which version do you want, ours or theirs?\n\nI believe we basically need support to apply different merge strategies\nto different files.\n\nI had similar problem a few times when I merged a long-standing branch\nand, after I saw the result of merge, I was basically satisfied, except\nI needed to revert a few sub-directories of the project (that gave huge\nnumber of conflicts), to their original state, either of my current\nbranch, or of the branch being merged, depending on particular case. You\nsee, I knew exactly what I needed, yet I was not able to achieve my goal\nwithout resorting to nasty kludges.\n\n> Normally merges are symmetric, so if you want non-symmetric behavior,\n> you have to define what it's supposed to be.\n\nYes, I'm ready to define what it's supposed to be. The problem is that\n\"git merge\" won't let me, due to lack of support to apply different\nmerge strategies to different files.\n\nAs I see it, first step of improvements could be to support\n\n  git merge -- <files>\n\nwhere selected strategy applies only to <files>, and the rest of files\nare kept intact (effectively applying \"ours\" strategy to them), along\nwith\n\n  git merge --exclude=<files>\n\n, to be able to exclude specific files (apply \"ours\" only to them)\nrather than include.\n\n[ As a side-note, please notice that after such changes, the \"ours\"\nstrategy could be deprecated (not that I think it should), as either:\n\n   git merge <branch> --\n\nor\n\n   git merge --exclude=. <branch>\n\nwould do the trick. ]\n\nThe next step would then be to support\n\n  git merge --force -- <files>\n\nthat would force to re-merge <files> with given strategy no matter what\ntheir current status in the index is.\n\nEven though such support would be enough for my specific use-case, it\ndoesn't provide suitable way to configure the default behavior. As a\nmore generic solution, a new syntax for \"git merge\" to specify what\nmerge strategy to apply to what files could be designed, and then\nability to put that syntax into a file for \"git merge\" to pick would\nsolve the problem of quasi-static configuration problem. Alternatively,\neven more generic .gitignore way of doing things apparently could be\nre-used to some degree by adding support for .gitmerge files.\n\n-- Sergey\n"},{"id":"400392","messageId":"51924543-3e26-8340-2105-1d08adcea196@iee.email","threadId":"53726","inReplyTo":"871rm6x86y.fsf@osv.gnss.ru","subject":"Re: Request for adding a simple mechanism to exclude files from Git merge operation","fromName":"Philip Oakley","fromEmail":"philipoakley@iee.email","sentAt":"2020-06-23T16:16:17Z","receivedAt":"2020-06-23T16:16:24Z","isPatch":false,"sender":{"key":"philipoakley@iee.email","avatar":"https://avatars.githubusercontent.com/u/914343?v=4"},"body":"On 23/06/2020 13:44, Sergey Organov wrote:\n> \"brian m. carlson\" <sandals@crustytoothpaste.net> writes:\n>\n>> On 2020-06-20 at 18:21:40, Tiran Meltser wrote:\n>>> Hi,\n>>> This topic is quite common in various use cases (e.g. production\n>>> configuration vs. staging one) and there are quite a few talks about\n>>> it in the web.\n>>> Nevertheless, there is no specific solution to this problem, only\n>>> partial workarounds (including the famous merge driver “ours”).\n>> In general, this is a hard problem.  When you perform a merge, you're\n>> asking to incorporate changes from both heads against a common merge\n>> base.  What does it mean when you want to merge two branches together\n>> but not make any changes?  Which version do you want, ours or theirs?\n> I believe we basically need support to apply different merge strategies\n> to different files.\n>\n> I had similar problem a few times when I merged a long-standing branch\n> and, after I saw the result of merge, I was basically satisfied, except\n> I needed to revert a few sub-directories of the project (that gave huge\n> number of conflicts), to their original state, either of my current\n> branch, or of the branch being merged, depending on particular case. You\n> see, I knew exactly what I needed, yet I was not able to achieve my goal\n> without resorting to nasty kludges.\n>\n>> Normally merges are symmetric, so if you want non-symmetric behavior,\n>> you have to define what it's supposed to be.\n> Yes, I'm ready to define what it's supposed to be. The problem is that\n> \"git merge\" won't let me, due to lack of support to apply different\n> merge strategies to different files.\n>\n> As I see it, first step of improvements could be to support\n>\n>   git merge -- <files>\n>\n> where selected strategy applies only to <files>, and the rest of files\n> are kept intact (effectively applying \"ours\" strategy to them),\nSo, essentially, for larger merges, this would be something like the\nrecent `--pathspec-from-file=<file>` series\nhttps://public-inbox.org/git/7324e091ba7f48e286e6c35c7b7c40490e5c85d1.1576778515.git.gitgitgadget@gmail.com/\nby Alexandr Miloslavskiy for the commands that did allow files to be\npassed in via `--` lists.\n\nIt would still require merge to be extended to include just a\n'partial-merge' or a 'file-merge' to clearly distinguish what is happening!\n\nThis still a symmetric merge, but with _author supplied_ pathspec\nlimiting, which is implicitly \"ours\" for the paths that are not merged.\n(I don't believe that the pathspec file can have negative pathspecs, so..)\n\n>  along\n> with\n>\n>   git merge --exclude=<files>\n>\n> , to be able to exclude specific files (apply \"ours\" only to them)\n> rather than include.\n\nOne difficulty of .precious lists, whether embedded or local, is the\nfalse impression that they provide any form of security to the user, so\nit needs a name that make that clear.\n>\n> [ As a side-note, please notice that after such changes, the \"ours\"\n> strategy could be deprecated (not that I think it should), as either:\n>\n>    git merge <branch> --\n>\n> or\n>\n>    git merge --exclude=. <branch>\n>\n> would do the trick. ]\n>\n> The next step would then be to support\n>\n>   git merge --force -- <files>\n>\n> that would force to re-merge <files> with given strategy no matter what\n> their current status in the index is.\nIsn't this already the same as the restore/checkout?\n\n>\n> Even though such support would be enough for my specific use-case, it\n> doesn't provide suitable way to configure the default behavior. As a\n> more generic solution, a new syntax for \"git merge\" to specify what\n> merge strategy to apply to what files could be designed, and then\n> ability to put that syntax into a file for \"git merge\" to pick would\n> solve the problem of quasi-static configuration problem. Alternatively,\n> even more generic .gitignore way of doing things apparently could be\n> re-used to some degree by adding support for .gitmerge files.\n>\n> -- Sergey\nPhilip\n"},{"id":"400395","messageId":"CABPp-BHa=jppGtoDiTz_NCXrd2zhTfALb_UrQjcF-VDcv+vuNA@mail.gmail.com","threadId":"53726","inReplyTo":"871rm6x86y.fsf@osv.gnss.ru","subject":"Re: Request for adding a simple mechanism to exclude files from Git merge operation","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2020-06-23T17:08:30Z","receivedAt":"2020-06-23T17:08:46Z","isPatch":false,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Tue, Jun 23, 2020 at 5:47 AM Sergey Organov <sorganov@gmail.com> wrote:\n>\n> \"brian m. carlson\" <sandals@crustytoothpaste.net> writes:\n>\n> > On 2020-06-20 at 18:21:40, Tiran Meltser wrote:\n> >> Hi,\n> >> This topic is quite common in various use cases (e.g. production\n> >> configuration vs. staging one) and there are quite a few talks about\n> >> it in the web.\n> >> Nevertheless, there is no specific solution to this problem, only\n> >> partial workarounds (including the famous merge driver “ours”).\n> >\n> > In general, this is a hard problem.  When you perform a merge, you're\n> > asking to incorporate changes from both heads against a common merge\n> > base.  What does it mean when you want to merge two branches together\n> > but not make any changes?  Which version do you want, ours or theirs?\n>\n> I believe we basically need support to apply different merge strategies\n> to different files.\n>\n> I had similar problem a few times when I merged a long-standing branch\n> and, after I saw the result of merge, I was basically satisfied, except\n> I needed to revert a few sub-directories of the project (that gave huge\n> number of conflicts), to their original state, either of my current\n> branch, or of the branch being merged, depending on particular case. You\n> see, I knew exactly what I needed, yet I was not able to achieve my goal\n> without resorting to nasty kludges.\n>\n> > Normally merges are symmetric, so if you want non-symmetric behavior,\n> > you have to define what it's supposed to be.\n>\n> Yes, I'm ready to define what it's supposed to be. The problem is that\n> \"git merge\" won't let me, due to lack of support to apply different\n> merge strategies to different files.\n>\n> As I see it, first step of improvements could be to support\n>\n>   git merge -- <files>\n>\n> where selected strategy applies only to <files>, and the rest of files\n> are kept intact (effectively applying \"ours\" strategy to them), along\n> with\n>\n>   git merge --exclude=<files>\n>\n> , to be able to exclude specific files (apply \"ours\" only to them)\n> rather than include.\n>\n> [ As a side-note, please notice that after such changes, the \"ours\"\n> strategy could be deprecated (not that I think it should), as either:\n>\n>    git merge <branch> --\n>\n> or\n>\n>    git merge --exclude=. <branch>\n>\n> would do the trick. ]\n>\n> The next step would then be to support\n>\n>   git merge --force -- <files>\n>\n> that would force to re-merge <files> with given strategy no matter what\n> their current status in the index is.\n>\n> Even though such support would be enough for my specific use-case, it\n> doesn't provide suitable way to configure the default behavior. As a\n> more generic solution, a new syntax for \"git merge\" to specify what\n> merge strategy to apply to what files could be designed, and then\n> ability to put that syntax into a file for \"git merge\" to pick would\n> solve the problem of quasi-static configuration problem. Alternatively,\n> even more generic .gitignore way of doing things apparently could be\n> re-used to some degree by adding support for .gitmerge files.\n\nI think you'd have an uphill battle to convince me that this isn't\nnet-negative value:\n  * You can just do \"git merge --no-commit ...; git restore\n[--source=<side>] -- <pathspec>\" to do what you're talking about\nabove.  I don't see the need to add extra functionality to merge,\nespecially not functionality that duplicates restore's functionality.\n  * The \"ours\" vs. \"theirs\" wording means you're going to have\nintrinsic problems with rebases.  Several users will like your choice\nof what \"ours\" means, the other half will complain that you've got it\nall wrong.  I think you need to let the users decide on a case-by-case\nbasis, and we have a handy \"git restore\" command for letting them do\nthat already.\n  * The pathspec limiting is going to be a bug factory for renaming\nhandling.  (The simplest form of which is just renaming a special path\nto a non-special path or vice-versa and modifying both sides of\nhistory.)  Rename handling can already get some pretty hairy corner\ncases without dumping more in the mix.  I'd rather have users decide\nwhat to do with paths that switched from being one of the special\n\"ours\" paths to being a normal 3-way-conflict marker path.  Luckily,\nwe already have a command that users can use to do this: git restore.\n  * I've run into \"branch-specific\" files in the wild and even\nsupported repositories that used them for years.  In my opinion, they\nare almost always nasty code smells that are artifacts from\nCVS/SVN-like thinking.  Although I wanted to stamp them out\nimmediately, there was opposition to it.  However, over time, people\nremoved those branch-specific files from the repository (and it wasn't\njust by me or at my prodding either; many were cleaned away by others\nwithout my involvement as other folks just found better ways to handle\nthings over time).  Giving special support to bad practices will just\nenshrine them, which I'd rather avoid.\n\nIf someone wants to spend their time here, I can't stop them.  Just be\naware that personally, I think it'd be a bad idea to make any\nmerge-recursive or merge-ort changes to support this kind of thing.\n(Alternatively, if you're still convinced this is a good idea, you can\nconsider this email a heads up about potential problem areas that you\nneed to address and areas where you'll need to craft some good\narguments to win over those who are skeptical.)\n\nHope that helps,\nElijah\n"},{"id":"400397","messageId":"87d05psnm1.fsf@osv.gnss.ru","threadId":"53726","inReplyTo":"51924543-3e26-8340-2105-1d08adcea196@iee.email","subject":"Re: Request for adding a simple mechanism to exclude files from Git merge operation","fromName":"Sergey Organov","fromEmail":"sorganov@gmail.com","sentAt":"2020-06-23T17:23:02Z","receivedAt":"2020-06-23T17:23:08Z","isPatch":false,"sender":{"key":"sorganov@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8501568?v=4"},"body":"Philip Oakley <philipoakley@iee.email> writes:\n\n\n[...]\n\n>> The next step would then be to support\n>>\n>>   git merge --force -- <files>\n>>\n>> that would force to re-merge <files> with given strategy no matter what\n>> their current status in the index is.\n> Isn't this already the same as the restore/checkout?\n\nI don't think it is. I meant it to be real (partial) merge, but\nperformed from the state where merge is already in progress, so affected\nfiles may have specific state in the index and in the work tree, both of\nwhich are to be discarded before the re-merge.\n\n-- Sergey\n"},{"id":"400450","messageId":"87sgelpmb2.fsf@osv.gnss.ru","threadId":"53726","inReplyTo":"CABPp-BHa=jppGtoDiTz_NCXrd2zhTfALb_UrQjcF-VDcv+vuNA@mail.gmail.com","subject":"Re: Request for adding a simple mechanism to exclude files from Git merge operation","fromName":"Sergey Organov","fromEmail":"sorganov@gmail.com","sentAt":"2020-06-23T20:19:29Z","receivedAt":"2020-06-23T21:24:41Z","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 Tue, Jun 23, 2020 at 5:47 AM Sergey Organov <sorganov@gmail.com> wrote:\n\n[...]\n\n>>\n>> I believe we basically need support to apply different merge strategies\n>> to different files.\n>>\n\n[...]\n\n>> > Normally merges are symmetric, so if you want non-symmetric behavior,\n>> > you have to define what it's supposed to be.\n>>\n>> Yes, I'm ready to define what it's supposed to be. The problem is that\n>> \"git merge\" won't let me, due to lack of support to apply different\n>> merge strategies to different files.\n>>\n>> As I see it, first step of improvements could be to support\n>>\n>>   git merge -- <files>\n>>\n>> where selected strategy applies only to <files>, and the rest of files\n>> are kept intact (effectively applying \"ours\" strategy to them), along\n>> with\n>>\n>>   git merge --exclude=<files>\n>>\n>> , to be able to exclude specific files (apply \"ours\" only to them)\n>> rather than include.\n>>\n>> [ As a side-note, please notice that after such changes, the \"ours\"\n>> strategy could be deprecated (not that I think it should), as either:\n>>\n>>    git merge <branch> --\n>>\n>> or\n>>\n>>    git merge --exclude=. <branch>\n>>\n>> would do the trick. ]\n>>\n>> The next step would then be to support\n>>\n>>   git merge --force -- <files>\n>>\n>> that would force to re-merge <files> with given strategy no matter what\n>> their current status in the index is.\n>>\n>> Even though such support would be enough for my specific use-case, it\n>> doesn't provide suitable way to configure the default behavior. As a\n>> more generic solution, a new syntax for \"git merge\" to specify what\n>> merge strategy to apply to what files could be designed, and then\n>> ability to put that syntax into a file for \"git merge\" to pick would\n>> solve the problem of quasi-static configuration problem. Alternatively,\n>> even more generic .gitignore way of doing things apparently could be\n>> re-used to some degree by adding support for .gitmerge files.\n>\n> I think you'd have an uphill battle to convince me that this isn't\n> net-negative value:\n>\n>   * You can just do \"git merge --no-commit ...; git restore\n> [--source=<side>] -- <pathspec>\" to do what you're talking about\n> above.  I don't see the need to add extra functionality to merge,\n> especially not functionality that duplicates restore's functionality.\n\nYeah, thanks, nice to know! I didn't, as \"restore\" is rather recent\naddition:\n\n$ git --version\ngit version 2.20.1\n$ git help restore\nNo manual entry for gitrestore\n\nHowever, it probably won't help with any other merge strategy anyway,\nright? E.g., think \"git merge -X ours\".\n\nIt's already admittedly better than nothing though!\n\n>   * The \"ours\" vs. \"theirs\" wording means you're going to have\n> intrinsic problems with rebases.  Several users will like your choice\n> of what \"ours\" means, the other half will complain that you've got it\n> all wrong.  I think you need to let the users decide on a case-by-case\n> basis, and we have a handy \"git restore\" command for letting them do\n> that already.\n\nI don't see how rebases are affected. I only suggested enhancements to\nthe merge-the-procedure, the \"git merge\" user command. Once merge is\nfinished and result is committed, there is (fortunately) now way for git\nto know how exactly the resulting content has been achieved.\n\nNor do I see why to limit decisions to \"ours\" vs \"theirs\". I meant to\nsupport arbitrary merge strategies for different files. Generic feature.\n\nMy thought was: if git at all supports different merge strategies, why\nnot to support different strategies for different files? I don't see any\ninherent contradiction in adding of such a feature.\n\n>   * The pathspec limiting is going to be a bug factory for renaming\n> handling.  (The simplest form of which is just renaming a special path\n> to a non-special path or vice-versa and modifying both sides of\n> history.)  Rename handling can already get some pretty hairy corner\n> cases without dumping more in the mix.  I'd rather have users decide\n> what to do with paths that switched from being one of the special\n> \"ours\" paths to being a normal 3-way-conflict marker path.\n\nI admittedly didn't dive into such details, but I didn't suggest to\nattach any additional attributes to paths either, so there is no need to\ncare about renames, as far as I'm able to see.\n\nApparently you talk about some other feature here that I didn't suggest.\n\n> Luckily, we already have a command that users can use to do this: git\n> restore.\n\n\"git restore\" is nice, but solves only very limited subset of merging\nstrategies we try to find solution for.\n\n>   * I've run into \"branch-specific\" files in the wild and even\n> supported repositories that used them for years.  In my opinion, they\n> are almost always nasty code smells that are artifacts from\n> CVS/SVN-like thinking.  Although I wanted to stamp them out\n> immediately, there was opposition to it.  However, over time, people\n> removed those branch-specific files from the repository (and it wasn't\n> just by me or at my prodding either; many were cleaned away by others\n> without my involvement as other folks just found better ways to handle\n> things over time).  Giving special support to bad practices will just\n> enshrine them, which I'd rather avoid.\n\nI didn't suggest any specific support for \"branch-specific\" files, nor\nto any bad practices, as far as I'm aware.\n\nOTOH, the generic feature I suggest, as any generic feature, could\nindeed be (ab)used in multiple ways, but it's not a problem of the\nfeature itself.\n\n> If someone wants to spend their time here, I can't stop them. Just be\n> aware that personally, I think it'd be a bad idea to make any\n> merge-recursive or merge-ort changes to support this kind of thing.\n\nHopefully your attitude is caused by some misunderstanding of the aim of\nmy suggestions.\n\n> (Alternatively, if you're still convinced this is a good idea, you can\n> consider this email a heads up about potential problem areas that you\n> need to address and areas where you'll need to craft some good\n> arguments to win over those who are skeptical.)\n\nI still don't see any potential problems. Could you please give an\nexplanatory example?\n\nLet me try to show my point by example. Suppose I've got a merge commit\nwhere part of files were merged with recursive strategy, part of files\n-- with the same recursive strategy but with -X ours, and the rest --\nwith the same recursive strategy and -X theirs. What problems,\nexactly, do you expect?\n\nIn fact I even fail to see how you will be able to tell it has been\nachieved with suggested feature rather than by manual resolution of all\nthe conflicts, so there must be no additional problems here.\n\nWhat do I miss?\n\nThanks,\n-- Sergey\n"},{"id":"400455","messageId":"CABPp-BFwNnD-zZvHjCAvvmzy1wTT3yy-smK5nCtQ937apaNmkQ@mail.gmail.com","threadId":"53726","inReplyTo":"87sgelpmb2.fsf@osv.gnss.ru","subject":"Re: Request for adding a simple mechanism to exclude files from Git merge operation","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2020-06-23T21:46:22Z","receivedAt":"2020-06-23T21:46:36Z","isPatch":false,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"Hi Sergey,\n\nOn Tue, Jun 23, 2020 at 1:19 PM Sergey Organov <sorganov@gmail.com> wrote:\n>\n> Elijah Newren <newren@gmail.com> writes:\n>\n> > On Tue, Jun 23, 2020 at 5:47 AM Sergey Organov <sorganov@gmail.com> wrote:\n>\n> [...]\n>\n> >>\n> >> I believe we basically need support to apply different merge strategies\n> >> to different files.\n> >>\n>\n> [...]\n>\n> >> > Normally merges are symmetric, so if you want non-symmetric behavior,\n> >> > you have to define what it's supposed to be.\n> >>\n> >> Yes, I'm ready to define what it's supposed to be. The problem is that\n> >> \"git merge\" won't let me, due to lack of support to apply different\n> >> merge strategies to different files.\n> >>\n> >> As I see it, first step of improvements could be to support\n> >>\n> >>   git merge -- <files>\n> >>\n> >> where selected strategy applies only to <files>, and the rest of files\n> >> are kept intact (effectively applying \"ours\" strategy to them), along\n> >> with\n> >>\n> >>   git merge --exclude=<files>\n> >>\n> >> , to be able to exclude specific files (apply \"ours\" only to them)\n> >> rather than include.\n> >>\n> >> [ As a side-note, please notice that after such changes, the \"ours\"\n> >> strategy could be deprecated (not that I think it should), as either:\n> >>\n> >>    git merge <branch> --\n> >>\n> >> or\n> >>\n> >>    git merge --exclude=. <branch>\n> >>\n> >> would do the trick. ]\n> >>\n> >> The next step would then be to support\n> >>\n> >>   git merge --force -- <files>\n> >>\n> >> that would force to re-merge <files> with given strategy no matter what\n> >> their current status in the index is.\n> >>\n> >> Even though such support would be enough for my specific use-case, it\n> >> doesn't provide suitable way to configure the default behavior. As a\n> >> more generic solution, a new syntax for \"git merge\" to specify what\n> >> merge strategy to apply to what files could be designed, and then\n> >> ability to put that syntax into a file for \"git merge\" to pick would\n> >> solve the problem of quasi-static configuration problem. Alternatively,\n> >> even more generic .gitignore way of doing things apparently could be\n> >> re-used to some degree by adding support for .gitmerge files.\n> >\n> > I think you'd have an uphill battle to convince me that this isn't\n> > net-negative value:\n> >\n> >   * You can just do \"git merge --no-commit ...; git restore\n> > [--source=<side>] -- <pathspec>\" to do what you're talking about\n> > above.  I don't see the need to add extra functionality to merge,\n> > especially not functionality that duplicates restore's functionality.\n>\n> Yeah, thanks, nice to know! I didn't, as \"restore\" is rather recent\n> addition:\n>\n> $ git --version\n> git version 2.20.1\n> $ git help restore\n> No manual entry for gitrestore\n>\n> However, it probably won't help with any other merge strategy anyway,\n> right? E.g., think \"git merge -X ours\".\n>\n> It's already admittedly better than nothing though!\n\nWell, I mean if we're talking about adding new features to git, then\nobviously we're only going to add them to new versions; in that\ncontext, a version from a year and a half ago is ancient.  ;-)\n\nGoing on the tangent for a second: if you can, please consider\nupgrading (and to something newer than the last release, 2.27.0) in\norder to help the community with testing the latest features,\nrefactors, and performance improvements.\n\n> >   * The \"ours\" vs. \"theirs\" wording means you're going to have\n> > intrinsic problems with rebases.  Several users will like your choice\n> > of what \"ours\" means, the other half will complain that you've got it\n> > all wrong.  I think you need to let the users decide on a case-by-case\n> > basis, and we have a handy \"git restore\" command for letting them do\n> > that already.\n>\n> I don't see how rebases are affected. I only suggested enhancements to\n> the merge-the-procedure, the \"git merge\" user command. Once merge is\n> finished and result is committed, there is (fortunately) now way for git\n> to know how exactly the resulting content has been achieved.\n\nSorry, the original email from Tiran wanted to be able to record\n\"branch-specific\" files and have merge automatically handle them\ndifferently.  You also alluded to that when you said\n\n\"\"\"\nAs a\nmore generic solution, a new syntax for \"git merge\" to specify what\nmerge strategy to apply to what files could be designed, and then\nability to put that syntax into a file for \"git merge\" to pick would\nsolve the problem of quasi-static configuration problem. Alternatively,\neven more generic .gitignore way of doing things apparently could be\nre-used to some degree by adding support for .gitmerge files.\n\"\"\"\n\nOnce you record the information for which files it applies to, then\nyou want it to happen whenever the merge machinery fires, right?\nRebasing, cherry-picking, and reverting are all created via the merge\nmachinery (even if they end up recording one parent instead of more).\nSaid another way, if merge automatically handles these special files,\neither rebase/cherry-pick/revert also handle the special files\nautomatically or you've just created a very inconsistent and weird\ndesign.\n\nIf you're disclaiming your last paragraph and saying that this would\nonly be a manual operation where the user specifies which files they\nwant to specially merge, then a lot of my complaints go away.\nAlthough...\n\n> Nor do I see why to limit decisions to \"ours\" vs \"theirs\". I meant to\n> support arbitrary merge strategies for different files. Generic feature.\n>\n> My thought was: if git at all supports different merge strategies, why\n> not to support different strategies for different files? I don't see any\n> inherent contradiction in adding of such a feature.\n\nIf you're interested in re-merging specific files, why not just call\n`git merge-file` to handle each one?  It supports e.g. --ours/--theirs\n(similar to merge's -Xours/-Xtheirs) and could possibly add more if\nthere are ones missing.  So, it seems like we already have a command\nfor this, even if it's less well known?\n\n> >   * The pathspec limiting is going to be a bug factory for renaming\n> > handling.  (The simplest form of which is just renaming a special path\n> > to a non-special path or vice-versa and modifying both sides of\n> > history.)  Rename handling can already get some pretty hairy corner\n> > cases without dumping more in the mix.  I'd rather have users decide\n> > what to do with paths that switched from being one of the special\n> > \"ours\" paths to being a normal 3-way-conflict marker path.\n>\n> I admittedly didn't dive into such details, but I didn't suggest to\n> attach any additional attributes to paths either, so there is no need to\n> care about renames, as far as I'm able to see.\n>\n> Apparently you talk about some other feature here that I didn't suggest.\n\nPerhaps your comments on creating a \".gitmerge\" file means something\ndifferent than I understood.  If it indeed does not record pathnames,\nthen the rename issue goes away (though then I don't understand what\nits purpose is nor the rest of your comments in that paragraph where\nyou suggested it).  But if your .gitmerge comments did imply something\nsimilar to .gitattributes which specified how certain paths were to be\nhandled, then renaming issues would certainly arise.\n\n> >   * I've run into \"branch-specific\" files in the wild and even\n> > supported repositories that used them for years.  In my opinion, they\n> > are almost always nasty code smells that are artifacts from\n> > CVS/SVN-like thinking.  Although I wanted to stamp them out\n> > immediately, there was opposition to it.  However, over time, people\n> > removed those branch-specific files from the repository (and it wasn't\n> > just by me or at my prodding either; many were cleaned away by others\n> > without my involvement as other folks just found better ways to handle\n> > things over time).  Giving special support to bad practices will just\n> > enshrine them, which I'd rather avoid.\n>\n> I didn't suggest any specific support for \"branch-specific\" files, nor\n> to any bad practices, as far as I'm aware.\n>\n> OTOH, the generic feature I suggest, as any generic feature, could\n> indeed be (ab)used in multiple ways, but it's not a problem of the\n> feature itself.\n>\n> > If someone wants to spend their time here, I can't stop them. Just be\n> > aware that personally, I think it'd be a bad idea to make any\n> > merge-recursive or merge-ort changes to support this kind of thing.\n>\n> Hopefully your attitude is caused by some misunderstanding of the aim of\n> my suggestions.\n\nWell, given that the last paragraph of your first email sounds (to me)\nto be contradictory to your statements in this email, it seems quite\nlikely I am misunderstanding something you have said.\n\n> > (Alternatively, if you're still convinced this is a good idea, you can\n> > consider this email a heads up about potential problem areas that you\n> > need to address and areas where you'll need to craft some good\n> > arguments to win over those who are skeptical.)\n>\n> I still don't see any potential problems. Could you please give an\n> explanatory example?\n>\n> Let me try to show my point by example. Suppose I've got a merge commit\n> where part of files were merged with recursive strategy, part of files\n> -- with the same recursive strategy but with -X ours, and the rest --\n> with the same recursive strategy and -X theirs. What problems,\n> exactly, do you expect?\n>\n> In fact I even fail to see how you will be able to tell it has been\n> achieved with suggested feature rather than by manual resolution of all\n> the conflicts, so there must be no additional problems here.\n>\n> What do I miss?\n\nThe problems I was raising were not with the resulting end-state tree\nthat users can construct or what happens with those trees once\nconstructed.  My problems were with expected automatic behavior from\nthe merge machinery coupled with incomplete specifications that\nsounded to me like a pile of corner cases and bugs that I'd have to\nfield while trying to maintain the merge machinery logic.\n\nOh, and I have a problem with \"branch specific\" files from the email\nyou were responding to.  I think those are a code smell.  But my\nprimary concern was the expectations of some new automatic behavior\nout of the merge machinery and how/if it gets configured.\n"},{"id":"400459","messageId":"xmqqk0zxbe6f.fsf@gitster.c.googlers.com","threadId":"53726","inReplyTo":"CABPp-BHa=jppGtoDiTz_NCXrd2zhTfALb_UrQjcF-VDcv+vuNA@mail.gmail.com","subject":"Re: Request for adding a simple mechanism to exclude files from Git merge operation","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-06-23T22:38:48Z","receivedAt":"2020-06-23T22:43:56Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Elijah Newren <newren@gmail.com> writes:\n\n> I think you'd have an uphill battle to convince me that this isn't\n> net-negative value:\n\n>   * You can just do \"git merge --no-commit ...; git restore ...\n\n>   * The \"ours\" vs. \"theirs\" wording means you're going to ...\n\n>   * The pathspec limiting is going to be a bug factory ...\n\n>   * I've run into \"branch-specific\" files in the wild and even\n> supported repositories that used them for years.  In my opinion, they\n> are almost always nasty code smells that are artifacts from\n> CVS/SVN-like thinking.  Although I wanted to stamp them out\n> immediately, there was opposition to it.  However, over time, people\n> removed those branch-specific files from the repository (and it wasn't\n> just by me or at my prodding either; many were cleaned away by others\n> without my involvement as other folks just found better ways to handle\n> things over time).  Giving special support to bad practices will just\n> enshrine them, which I'd rather avoid.\n\nAlso if you consider what would happen to future merges after making\nsuch a half-merge, you would not recommend it, whether with an even\neasier \"feature\" to encourage a bad workflow or with existing tools.\n\nEvery time you create a commit (be it a single parent commit or a\nmerge commit with multiple parents), you are making this statement:\n\n    Where the histories leading to the parent commits want to go\n    aligns with my goal, and with this commit, I am extending their\n    effort to get us even closer to our shared goal.\n\nAfter a side branch forked and worked on two parts of the system (A\nand B) while the mainline did not do anything to these two parts but\nworked on other parts, you look at the histories (not just the trees\nof tip commits) leading to the current mainline and the tip of the\nside branch, convince yourself that you agree with both of the\nchanges the side branch made to A and B, and because the mainline\nleft these two parts intact, you take their changes wholesale and\nrecord the result in a merge commit.  Because you also made sure all\nthe other developments happened while the side branch forked took\nyou closer to your goal, you too them too, so the resulting merge\ncommit records a tree that is closer to either of its parents to\nyour goal.\n\nAnd readers cannot dismiss this fact as mere philosophy; it is\nfundamental and ingrained in the behaviour of Git tools,\nspecifically how three-way merge works.\n\nOnce you dismiss a part of what a side branch did as irrelevant by\ntaking \"our\" version for selected paths in a merge, the goal you had\nwhen you made the merge will no longer align with the goal the folks\nwho worked on the side branch had.  Perhaps you only took changes to\nthe A part and discarded changes to the B part they made, because it\nsuited your goal better.  Now after the folks who care about both\nparts further work on part A and B, you may try to merge their work\ninto the updated mainline (whose history contains the declaration\nyou made earlier that the work did on the B part made up to the\npoint you made the earlier merge is worthless).  The new merge will\nuse the older tip of the side branch that was partially merged with\nthe old merge as the merge base and will consider what was done on\nthe side branch (which would contain changes to both A and B---after\nall they care about both A and B).  This mismatch will either cause\nheavy conflicts in part B, or (worse yet) silent mismerges.\n\nSo in short, sure, you can use the existing machinery, or invent a\nnew \"easier\" machinery, to create and record such a half-merge, and\nyou may declare victory after creating your first such merge.  But\nyou left a disaster for future merges from the same side branch by\ndoing so.\n\nAs to handling configuration files, what you and Brian mentioned to\nkeep recommended template(s) in-tree and have the build procedure\ncopy it out and keeping the customization out of merge is the BCP.\nWe shouldn't butcher the tool and make it even easier to use a bad\nworkflow, as you said.\n\nThanks.\n\n"},{"id":"400470","messageId":"CAPx1Gvc6X5zgHXfnaKD+sBM=P1ve4raR5tJzTaZnwwTugBva_A@mail.gmail.com","threadId":"53726","inReplyTo":"CABPp-BFwNnD-zZvHjCAvvmzy1wTT3yy-smK5nCtQ937apaNmkQ@mail.gmail.com","subject":"Re: Request for adding a simple mechanism to exclude files from Git merge operation","fromName":"Chris Torek","fromEmail":"chris.torek@gmail.com","sentAt":"2020-06-23T22:57:38Z","receivedAt":"2020-06-23T22:57:53Z","isPatch":false,"sender":{"key":"chris.torek@gmail.com","avatar":"https://avatars.githubusercontent.com/u/16826774?v=4"},"body":"I'm going to snip a lot here as I'm not really replying to one\nspecific proposal or another.  I just want to add some background:\n\nOn Tue, Jun 23, 2020 at 2:48 PM Elijah Newren <newren@gmail.com> wrote:\n> Once you record the information for which files it applies to, then\n> you want it to happen whenever the merge machinery fires, right?\n\nThis is, of course, already the case for merge drivers defined and\nused in .gitattributes entries (though note that they don't apply to some\nmerge *strategies*, e.g., `-s ours` completely ignores them).\n\n> The problems I was raising were not with the resulting end-state tree\n> that users can construct or what happens with those trees once\n> constructed.  My problems were with expected automatic behavior from\n> the merge machinery coupled with incomplete specifications that\n> sounded to me like a pile of corner cases and bugs that I'd have to\n> field while trying to maintain the merge machinery logic.\n\nThis is already a bit of a problem with merge drivers in .gitattributes.\nIn particular, suppose we're doing a standard merge of commits H\n(HEAD) and T (theirs) with respect to B (base).  If the file is named\n\"foo\" and there is a merge driver defined for \"foo\", this merge driver\nis completely ignored *unless* all three copies of foo differ!  And of\ncourse there are rename issues if a file's name was foo but isn't now\nor vice versa.\n\nI do think it might be reasonable to be able to mark a merge driver\nas \"always use this, even if two or even all three inputs are the same\".\n\n> Oh, and I have a problem with \"branch specific\" files from the email\n> you were responding to.  I think those are a code smell.  But my\n> primary concern was the expectations of some new automatic behavior\n> out of the merge machinery and how/if it gets configured.\n\nThey're not only smelly :-) ... they don't even really mean anything.\nIn particular, merge works not on *branches* but on *commits*.  If\nwe're merging commits H and T with base B, we may not be on any\nbranch at all (detached HEAD) and there could be anywhere from\nzero to arbitrarily many branch names pointing at or containing each\nof the three commits.  But of course it's common to have one branch\nname for each of H and T, and that's where most people who want\nthis are coming from.\n\nIn any case, the merge driver stuff is useful to some people sometimes.\nIt might be a little more useful if you could force `git merge` to use it\neven if only \"their side\" of the merge has changed the file since the\nmerge base.\n\nChris\n"},{"id":"400549","messageId":"87k0zw1gu9.fsf@osv.gnss.ru","threadId":"53726","inReplyTo":"xmqqk0zxbe6f.fsf@gitster.c.googlers.com","subject":"Re: Request for adding a simple mechanism to exclude files from Git merge operation","fromName":"Sergey Organov","fromEmail":"sorganov@gmail.com","sentAt":"2020-06-24T18:03:42Z","receivedAt":"2020-06-24T18:03:52Z","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> Elijah Newren <newren@gmail.com> writes:\n>\n>> I think you'd have an uphill battle to convince me that this isn't\n>> net-negative value:\n>\n>>   * You can just do \"git merge --no-commit ...; git restore ...\n>\n>>   * The \"ours\" vs. \"theirs\" wording means you're going to ...\n>\n>>   * The pathspec limiting is going to be a bug factory ...\n>\n>>   * I've run into \"branch-specific\" files in the wild and even\n>> supported repositories that used them for years.  In my opinion, they\n>> are almost always nasty code smells that are artifacts from\n>> CVS/SVN-like thinking.  Although I wanted to stamp them out\n>> immediately, there was opposition to it.  However, over time, people\n>> removed those branch-specific files from the repository (and it wasn't\n>> just by me or at my prodding either; many were cleaned away by others\n>> without my involvement as other folks just found better ways to handle\n>> things over time).  Giving special support to bad practices will just\n>> enshrine them, which I'd rather avoid.\n>\n> Also if you consider what would happen to future merges after making\n> such a half-merge, you would not recommend it, whether with an even\n> easier \"feature\" to encourage a bad workflow or with existing tools.\n>\n> Every time you create a commit (be it a single parent commit or a\n> merge commit with multiple parents), you are making this statement:\n>\n>     Where the histories leading to the parent commits want to go\n>     aligns with my goal, and with this commit, I am extending their\n>     effort to get us even closer to our shared goal.\n>\n> After a side branch forked and worked on two parts of the system (A\n> and B) while the mainline did not do anything to these two parts but\n> worked on other parts, you look at the histories (not just the trees\n> of tip commits) leading to the current mainline and the tip of the\n> side branch, convince yourself that you agree with both of the\n> changes the side branch made to A and B, and because the mainline\n> left these two parts intact, you take their changes wholesale and\n> record the result in a merge commit.  Because you also made sure all\n> the other developments happened while the side branch forked took\n> you closer to your goal, you too them too, so the resulting merge\n> commit records a tree that is closer to either of its parents to\n> your goal.\n>\n> And readers cannot dismiss this fact as mere philosophy; it is\n> fundamental and ingrained in the behaviour of Git tools,\n> specifically how three-way merge works.\n>\n> Once you dismiss a part of what a side branch did as irrelevant by\n> taking \"our\" version for selected paths in a merge, the goal you had\n> when you made the merge will no longer align with the goal the folks\n> who worked on the side branch had.  Perhaps you only took changes to\n> the A part and discarded changes to the B part they made, because it\n> suited your goal better.  Now after the folks who care about both\n> parts further work on part A and B, you may try to merge their work\n> into the updated mainline (whose history contains the declaration\n> you made earlier that the work did on the B part made up to the\n> point you made the earlier merge is worthless).  The new merge will\n> use the older tip of the side branch that was partially merged with\n> the old merge as the merge base and will consider what was done on\n> the side branch (which would contain changes to both A and B---after\n> all they care about both A and B).  This mismatch will either cause\n> heavy conflicts in part B, or (worse yet) silent mismerges.\n\nWhat is suggested is exactly a way to deal with heavy merge conflicts in\nthe first place, in particular, in the example you use, by telling git\nthat we are not interested in the side-changes in a given set of files.\nNever.\n\nIf we change our mind later, we will simply need to start merging from\nthe point before that old, now rendered wrong, decision took place.\n\nOTOH, if one tries to abuse the feature for different purposes, it will\nhurt sooner than later, no questions.\n\n>\n> So in short, sure, you can use the existing machinery, or invent a\n> new \"easier\" machinery, to create and record such a half-merge, and\n> you may declare victory after creating your first such merge.  But\n> you left a disaster for future merges from the same side branch by\n> doing so.\n\nI think I at least understand most of what you said, except I wasn't\nable to figure what the definition of \"half-merge\", or \"partial merge\"\nis.\n\nTo clarify, could you please tell if plain\n\n   git merge -s ours\n\nis a \"partial merge\" from your point of view?\n\nIf you think it is not, then what about:\n\n  git merge -X ours\n\n? Is it a \"partial merge\"?\n\nThanks,\n-- Sergey\n"},{"id":"400553","messageId":"87ftak1di9.fsf@osv.gnss.ru","threadId":"53726","inReplyTo":"CABPp-BFwNnD-zZvHjCAvvmzy1wTT3yy-smK5nCtQ937apaNmkQ@mail.gmail.com","subject":"Re: Request for adding a simple mechanism to exclude files from Git merge operation","fromName":"Sergey Organov","fromEmail":"sorganov@gmail.com","sentAt":"2020-06-24T19:15:42Z","receivedAt":"2020-06-24T19:15:48Z","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 Sergey,\n>\n> On Tue, Jun 23, 2020 at 1:19 PM Sergey Organov <sorganov@gmail.com> wrote:\n\n[...]\n\n>> I don't see how rebases are affected. I only suggested enhancements to\n>> the merge-the-procedure, the \"git merge\" user command. Once merge is\n>> finished and result is committed, there is (fortunately) now way for git\n>> to know how exactly the resulting content has been achieved.\n>\n> Sorry, the original email from Tiran wanted to be able to record\n> \"branch-specific\" files and have merge automatically handle them\n> differently.  You also alluded to that when you said\n>\n> \"\"\"\n> As a\n> more generic solution, a new syntax for \"git merge\" to specify what\n> merge strategy to apply to what files could be designed, and then\n> ability to put that syntax into a file for \"git merge\" to pick would\n> solve the problem of quasi-static configuration problem. Alternatively,\n> even more generic .gitignore way of doing things apparently could be\n> re-used to some degree by adding support for .gitmerge files.\n> \"\"\"\n>\n> Once you record the information for which files it applies to, then\n> you want it to happen whenever the merge machinery fires, right?\n\nNo. I didn't mean it, no way. I wanted only \"git merge\" to be affected.\n\n> Rebasing, cherry-picking, and reverting are all created via the merge\n> machinery (even if they end up recording one parent instead of more).\n> Said another way, if merge automatically handles these special files,\n> either rebase/cherry-pick/revert also handle the special files\n> automatically or you've just created a very inconsistent and weird\n> design.\n\nI disagree. The fact that all of the mentioned commands reuse internal\nmerge implementation is a good thing, but it's irrelevant to the case at\nhand. I never merge side-branches with either of\nrebase/cherry-pick/revert, so it's only logical to ask for specific\nbranch-merging functionality only from \"git merge\".\n\nI don't even want to think for now if it could be useful in\nrebase/cherry-pick/revert/whatever, as it's already difficult enough.\n\nAs a side note, if anything, in my POV, having both rebase and\ncherry-pick in porcelain is an overkill. Effectively, 'rebase' is a\n'cherry-pick' on steroids, so adding a --cherry option to 'rebase' seems\nto be logical.\n\n>\n> If you're disclaiming your last paragraph and saying that this would\n> only be a manual operation where the user specifies which files they\n> want to specially merge, then a lot of my complaints go away.\n\nNothing to disclaim, I think. What I thought was that it will affect\nthings automatically, but only for \"git merge\". Apparently generic merge\nmachinery will need support for this, but it will be used only for \"git\nmerge\", at least for a start. Alternatively, there could be generic\noption that will turn this handling on, and this option will be turned\non by default only for \"git merge\". I'm not familiar with Git\nimplementation enough to even try suggest the right way to implement it\nthough.\n\n> Although...\n>\n>> Nor do I see why to limit decisions to \"ours\" vs \"theirs\". I meant to\n>> support arbitrary merge strategies for different files. Generic feature.\n>>\n>> My thought was: if git at all supports different merge strategies, why\n>> not to support different strategies for different files? I don't see any\n>> inherent contradiction in adding of such a feature.\n>\n> If you're interested in re-merging specific files, why not just call\n> `git merge-file` to handle each one?  It supports e.g. --ours/--theirs\n> (similar to merge's -Xours/-Xtheirs) and could possibly add more if\n> there are ones missing.  So, it seems like we already have a command\n> for this, even if it's less well known?\n\nmerge-file is likely some low-level utility... check... yeah, it is.\nExtremely low-level. Three-way merge of 3 /files/. How does it help? How\nmuch error-prone scripting will I need to get to the point of any\nsuitable result?\n\nTo me what you suggest here is basically what I've described as kludgy\nway of achieving the goal. I can probably also make merges with\ndifferent strategies in 2 different repositories, then copy files\nbetween them. Does it mean I already have all the needed tools to get\nthe job done?\n\nPlease consider the problem: I did a regular merge, and by analysis of\nthe resulting conflicts I realized I'd need to visit a few tens of files\nand resolve conflicts exactly the way -X ours would. Suppose, for\nsimplicity, that all these files are in some sub-directory <subdir>.\n\ngit merge --force -X ours -- <subdir>\n\nwould solve this immediately, if it existed. Honestly, I can't even\nestimate what would I need to do to achieve it using \"git merge-file\". I\nmean, I guess it's possible, yet I don't believe it's practical.\n\n>> >   * The pathspec limiting is going to be a bug factory for renaming\n>> > handling.  (The simplest form of which is just renaming a special path\n>> > to a non-special path or vice-versa and modifying both sides of\n>> > history.)  Rename handling can already get some pretty hairy corner\n>> > cases without dumping more in the mix.  I'd rather have users decide\n>> > what to do with paths that switched from being one of the special\n>> > \"ours\" paths to being a normal 3-way-conflict marker path.\n>>\n>> I admittedly didn't dive into such details, but I didn't suggest to\n>> attach any additional attributes to paths either, so there is no need to\n>> care about renames, as far as I'm able to see.\n>>\n>> Apparently you talk about some other feature here that I didn't suggest.\n>\n> Perhaps your comments on creating a \".gitmerge\" file means something\n> different than I understood.  If it indeed does not record pathnames,\n> then the rename issue goes away (though then I don't understand what\n> its purpose is nor the rest of your comments in that paragraph where\n> you suggested it).  But if your .gitmerge comments did imply something\n> similar to .gitattributes which specified how certain paths were to be\n> handled, then renaming issues would certainly arise.\n\nWell, I had no use for .gitattributes, so I didn't even recall they\nexist. Maybe it's where needed support could be defined, so that\nexisting renames handling machinery is simply reused without additional\nefforts. Will it work right now if I define custom merge driver that\ndoes \"git merge -X ours\" and then assign it to the set of files? It'd\nstill be a kludge, but one that proves the point that such support could\nbe implemented without much effort.\n\nOTOH, as I already said, my own use-case doesn't need any permanent\nconfiguration, so what I say about it is mostly just thinking aloud. In\nparticular, the .gitattributes trick above is again too complex to solve\na casual but heavy problem I sometimes have, though I think I'd still\nuse it lacking better way.\n\nThanks,\n-- Sergey\n"},{"id":"400561","messageId":"xmqqk0zw5bt5.fsf@gitster.c.googlers.com","threadId":"53726","inReplyTo":"87k0zw1gu9.fsf@osv.gnss.ru","subject":"Re: Request for adding a simple mechanism to exclude files from Git merge operation","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-06-24T22:38:46Z","receivedAt":"2020-06-24T22:38: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> To clarify, could you please tell if plain\n>\n>    git merge -s ours\n>\n> is a \"partial merge\" from your point of view?\n\nIt is not even \"partial\".\n\nThe merge strategy \"-s ours\" is a way to cauterize a side branch as\ndead-end, declaring that everything that has ever been done on that\nside branch up to the point of the merge is not interesting and we'd\nnever want to look at anything that builds on it.\n\nIt has its uses, though.  After doing so, \"git log --all ^mainline\"\nor \"git branch --not-merged release\" would not show such a\ncauterized branch; it is a good way to \"hide\" the branch that you\ndeem a dead-end when you cannot remove it.  But of course you do not\nwant to ever build on such a side branch after doing so.\n\n> If you think it is not, then what about:\n>\n>   git merge -X ours\n\nIt is not even a sensible merge.  It takes their changes where we\ndidn't touch, but it takes our change without even looking at what\nthey did when the changes overlap.  It's like saying\n\n\tlet's take as much automerge results as possible to salvage\n\ttheir changes where our work does not overlap with what they\n\tdid on their side branch, but in places that textually\n\tconflict, I would not bother trying to understand what they\n\twanted to do well enough to be able to reimplement it for\n\tthem within the context of the current code we updated to.\n\nIt is better than letting monkeys type randomly and claim that they\nresolved conflicts, but not by a large margin ;-)\n\nSee also https://lore.kernel.org/git/7vr69r8sqk.fsf@gitster.siamese.dyndns.org/\nthat is more than 10 years old.\n\nImagine you have two (for simplicity) areas of interest, each is\nworked by a different team, A and B, whose work are in directories\ndir-A and dir-B of the project.  The teams work on their own topic\nbranches and from time to time merge to the \"development\" branch for\nintegration testing.  Time flows from left to right.\n\n\n    ---A---A---A---A---A\tteam A\n                \\       \\\n      ---X---X---X---X---X\tintegration testing\n            /       /\n    ---B---B---B---B\t\tteam B\n\nAfter a while, team A may be tempted to say \"we are done, so let's\nmerge our work to the release branch\", but the work product of team\nB may be far from ready.\n\nIf teams have been keeping good branch hygiene, such a merge to\nrelease branch may be done by merging the rightmost commit on A\nbranch directly to the release branch and there is no need for a\n\"partial merge that merges only dir-A while ignoring dir-B\".  But if\nwe start supporting such a feature, it becomes tempting to use such\na \"(mis)feature\" to merge the rightmost commit on the integration\nbranch X to the release branch.  Some may find it even necessary\nbecause A's branch may contain backmerges from the integration\ntesting branch, hence contaminated by unfinished work by team B.\n\nThe resulting tree of such a partial merge from integration testing\nbranch may be the same as a proper \"merge of topic branch A into\nrelease\" for this \"first\" merge by team A, but the consequence it\nleaves for team B would be nasty.  After building a bit more on what\nthey had on the branch B, it may become ready to release their part,\nbut because of the partial merge that declared that team B's effort\non dir-B before the point of the first merge is worthless, the\nrelease branch, even though it would already have the four commits\nlabelled as B in the picture contained, has none of the actual\nchanges reflected in its tree.  The result would be like cherry\npicking only recent work on team B's branch, not the whole thing.\n\nAnd that is why such a \"pathspec limited\" merge is a way to\ndisaster that encourages a bad workflow.\n\nThanks.\n"},{"id":"400578","messageId":"87h7uzweoh.fsf@osv.gnss.ru","threadId":"53726","inReplyTo":"xmqqk0zw5bt5.fsf@gitster.c.googlers.com","subject":"Re: Request for adding a simple mechanism to exclude files from Git merge operation","fromName":"Sergey Organov","fromEmail":"sorganov@gmail.com","sentAt":"2020-06-25T11:46:54Z","receivedAt":"2020-06-25T11:47:00Z","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>> To clarify, could you please tell if plain\n>>\n>>    git merge -s ours\n>>\n>> is a \"partial merge\" from your point of view?\n>\n> It is not even \"partial\".\n\nOK, get it, thanks!\n\nI asked for clarification because it /is/ possible to interpret such\nmerge as \"partial\" in the sense that it gets only /part/ of changes,\ndiscarding those that were introduced on the side branch.\n\n>\n> The merge strategy \"-s ours\" is a way to cauterize a side branch as\n> dead-end, declaring that everything that has ever been done on that\n> side branch up to the point of the merge is not interesting and we'd\n> never want to look at anything that builds on it.\n>\n> It has its uses, though.  After doing so, \"git log --all ^mainline\"\n> or \"git branch --not-merged release\" would not show such a\n> cauterized branch; it is a good way to \"hide\" the branch that you\n> deem a dead-end when you cannot remove it.  But of course you do not\n> want to ever build on such a side branch after doing so.\n>\n\nI think the usefulness of the feature might happen to be somewhat wider,\nyet I'm to avoid arguing, to scatter no attention.\n\n>> If you think it is not, then what about:\n>>\n>>   git merge -X ours\n>\n> It is not even a sensible merge.\n\nI don't believe one could tell out of context, see below.\n\nAnyway, the question was not if it's good, bad, or sensible. Suppose I\ndo such a \"non-sensible\" merge, is it a \"partial merge\" or not?\n\n> It takes their changes where we didn't touch, but it takes our change\n> without even looking at what they did when the changes overlap.\n\nSure, and that happens to be exactly what I need from Git when I do such\nmerge, because I did look at all the 137 conflicts and found none where\nI need different resolution; and yes, I'm too lazy to resolve all 137 by\nhand. Makes sense? Is my merge \"partial\" /now/?\n\nGetting back to technical discussion, can we come up with a useful\ndefinition of \"partial merge\" at all? Honestly, I can't, and unless\nsomebody else does, I'm inclined to consider it to be an arbitrary label\nbeing put on selected merge examples for the sake of argument.\n\nThanks,\n-- Sergey\n"}]}