{"thread":{"id":"61172","subject":"Merge selected files or folders","startedAt":"2024-03-21T16:55:43Z","lastAt":"2024-03-22T17:23:44Z","messageCount":7,"participants":["Richard Kerry","Junio C Hamano","Sergey Organov","Konstantin Khomoutov","Dragan Simic","stefan.naewe@atlas-elektronik.com"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"491160","messageId":"PA4PR07MB7406FAC1F8C00E29979FCFF59E322@PA4PR07MB7406.eurprd07.prod.outlook.com","threadId":"61172","inReplyTo":null,"subject":"Merge selected files or folders","fromName":"Richard Kerry","fromEmail":"richard.kerry@eviden.com","sentAt":"2024-03-21T16:50:30Z","receivedAt":"2024-03-21T16:55:43Z","isPatch":false,"sender":{"key":"richard.kerry@eviden.com","avatar":null},"body":"\nI'd like to merge only certain files, or folders, from another branch.  What command or options should I be looking at to get this done?\n\nWhat keywords should I be looking at?  When I ask Google I seem to find various answers which then get analysed as \"actually don't do it like this, because it doesn't actually do a merge\" or other unsatisfactory results.\nMy colleague is mostly working on \"master\" and I am mostly working on a branch.  In most cases my branch should fast-forward to the head of master, so I'd have thought that behind the scenes it would just need to re-point the commit identifier, so there ought to be a straightforward implementation of this.\n\nI know git expects to merge a whole branch throughout the repository, but this seems like something I can't be the only person ever to want, so I assume there is a \"proper\" way of doing it.  Or do I merge all then clear everything I don't want, which seems tedious.\n\nRegards,\nRichard.\n\n\n\t\n"},{"id":"491164","messageId":"xmqqbk778oeb.fsf@gitster.g","threadId":"61172","inReplyTo":"PA4PR07MB7406FAC1F8C00E29979FCFF59E322@PA4PR07MB7406.eurprd07.prod.outlook.com","subject":"Re: Merge selected files or folders","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-03-21T17:50:52Z","receivedAt":"2024-03-21T17:50:55Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Richard Kerry <richard.kerry@eviden.com> writes:\n\n> I'd like to merge only certain files, or folders, from another\n> branch.  What command or options should I be looking at to get\n> this done?\n\nIf you are using the verb \"merge\" in the way Git uses, then there is\n*no* option to do so and that is very much deliberate, as allowing\nsuch a operation will break your history.\n\nA \"merge\" commit in Git records the fact that *all* changes that\nwere done in each parent since the merged branches diverged have\nbeen considered and the tree recorded by the merge commit is the\nresult.  Hence, if you later change your mind and \"merge\" other\nchanges from the same branch, it will result in no change at all, by\ndefinition.\n\nBut if you are porting some changes made on another branch to the\ncurrent branch, and then planning to record the result as a regular\nsingle parent commit, then there is no fundamental reason to forbid\nsuch an operation.  It is what cherry-pick ought to be able to do,\neven though I do not think it accepts a pathspec to limit currently.\n\nAssuming a history of this shape:\n\n      x---x---X (that other branch)\n     /\n    O---o---o---o---H\t(current branch)\n\nsuch a \"cherry-pick\" would essentially be applying all the changes\nlead to X since the histories forked at O on top of H:\n\n    $ git checkout H\n    $ O=$(git merge-base X H)\n    $ git diff $O X | git apply\n    $ git commit -m \"picked changes from branch X\"\n\nAnd if you want to limit the paths involved in the operation, the\n\"git diff\" step can be given a <pathspec> to limit the changes that\nare ported.\n\n    $ git checkout H\n    $ O=$(git merge-base X H)\n    $ git diff $O X -- thisdir/ that/file | git apply\n    $ git commit -m \"picked changes from branch X\"\n\nTeaching \"git cherry-pick\" to accept a pathspec and natively \nperform something like the above is left as an exercise.\n\nHTH\n"},{"id":"491224","messageId":"87bk76fvvr.fsf@osv.gnss.ru","threadId":"61172","inReplyTo":"xmqqbk778oeb.fsf@gitster.g","subject":"Re: Merge selected files or folders","fromName":"Sergey Organov","fromEmail":"sorganov@gmail.com","sentAt":"2024-03-22T09:39:36Z","receivedAt":"2024-03-22T09:39:40Z","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> Richard Kerry <richard.kerry@eviden.com> writes:\n>\n>> I'd like to merge only certain files, or folders, from another\n>> branch.  What command or options should I be looking at to get\n>> this done?\n>\n> If you are using the verb \"merge\" in the way Git uses, then there is\n> *no* option to do so and that is very much deliberate, as allowing\n> such a operation will break your history.\n\nNo, it won't break history. The merge commit *content* does not break\n*history* in any way. Path-limiting makes perfect sense when one is\nabout to create merge commit content and knows in advance the exact set\nof paths the changes from which are to be included (or ignored).\n\n>\n> A \"merge\" commit in Git records the fact that *all* changes that\n> were done in each parent since the merged branches diverged have\n> been considered and the tree recorded by the merge commit is the\n> result.  Hence, if you later change your mind and \"merge\" other\n> changes from the same branch, it will result in no change at all, by\n> definition.\n\nYes, but it's not an argument against path limiting support in the merge\n*command* that is just a helper to create merge commits. With this\nfeature in place I'd just tell \"git merge\" that I've already considered\nall the other paths and decided that changes from them are irrelevant\nand are not to be included.\n\n> But if you are porting some changes made on another branch to the\n> current branch, and then planning to record the result as a regular\n> single parent commit, then there is no fundamental reason to forbid\n> such an operation.  It is what cherry-pick ought to be able to do,\n> even though I do not think it accepts a pathspec to limit currently.\n\nI think both cherry-pick and merge can be given such a possibility, as\nthere is nothing wrong with it (see above), provided we do properly\ndocument what we are actually doing.\n\n>\n> Assuming a history of this shape:\n>\n>       x---x---X (that other branch)\n>      /\n>     O---o---o---o---H\t(current branch)\n>\n> such a \"cherry-pick\" would essentially be applying all the changes\n> lead to X since the histories forked at O on top of H:\n>\n>     $ git checkout H\n>     $ O=$(git merge-base X H)\n>     $ git diff $O X | git apply\n>     $ git commit -m \"picked changes from branch X\"\n>\n> And if you want to limit the paths involved in the operation, the\n> \"git diff\" step can be given a <pathspec> to limit the changes that\n> are ported.\n>\n>     $ git checkout H\n>     $ O=$(git merge-base X H)\n>     $ git diff $O X -- thisdir/ that/file | git apply\n>     $ git commit -m \"picked changes from branch X\"\n>\n> Teaching \"git cherry-pick\" to accept a pathspec and natively \n> perform something like the above is left as an exercise.\n\nWell, I'd argue that both cherry-pick and merge should learn to have\nthis useful feature, and it's much more useful for merges, as, unlike\nsingle commits the cherry-pick deals with, the merges tend to be huge\nfrom time to time, making manual amendments a real pain.\n\nDo such patches have a chance of being accepted?\n\nThanks,\n-- Sergey Organov\n"},{"id":"491228","messageId":"20240322095640.saas2lxwmitrwoki@carbon","threadId":"61172","inReplyTo":"87bk76fvvr.fsf@osv.gnss.ru","subject":"Re: Merge selected files or folders","fromName":"Konstantin Khomoutov","fromEmail":"kostix@bswap.ru","sentAt":"2024-03-22T09:56:40Z","receivedAt":"2024-03-22T10:12:12Z","isPatch":false,"sender":{"key":"kostix@bswap.ru","avatar":null},"body":"On Fri, Mar 22, 2024 at 12:39:36PM +0300, Sergey Organov wrote:\n\n>>> I'd like to merge only certain files, or folders, from another\n>>> branch.  What command or options should I be looking at to get\n>>> this done?\n>>\n>> If you are using the verb \"merge\" in the way Git uses, then there is\n>> *no* option to do so and that is very much deliberate, as allowing\n>> such a operation will break your history.\n> \n> No, it won't break history. The merge commit *content* does not break\n> *history* in any way. Path-limiting makes perfect sense when one is\n> about to create merge commit content and knows in advance the exact set\n> of paths the changes from which are to be included (or ignored).\n\nThis reminded me of the \"disaster no. 2\" in the rant, arguably famous at the\ntime [1], in particular: \n\n| One user of Tortoise Git would do a pull, have a merge conflict, resolve the\n| merge conflict, and then look carefully at his list of files to be committed\n| back when he was committing the results. There were lots of files there, and\n| he knew that the merge conflict only involved a couple of files. For his\n| commit, he unchecked all the other files changes that he was not involved\n| in, committed the results and pushed the commit.\n\nMy understanding is that the OP actually wanted to create a similar situation\nconsciously. It's quite possible that they intend to never merge the results\nback into \"the main line\" but anyway.\n\nThe point is, the feature you're advocating is bound to be abused exactly\nthrough this \"this is my stuff, and there is the stuff I do not care about\"\nattitude.\n\nHaving said that, I do not oppose these features (not that my opinion should\nhave any weight; I'm just making things clear) as in the end the only workable\nsolution to have decent quality of a project's content is \"gatekeeping\" the\nchanges by the review process.\n\n 1. https://randyfay.com/content/avoiding-git-disasters-gory-story\n\n"},{"id":"491230","messageId":"838ca1b39625dea6827fa623abb51792@manjaro.org","threadId":"61172","inReplyTo":"20240322095640.saas2lxwmitrwoki@carbon","subject":"Re: Merge selected files or folders","fromName":"Dragan Simic","fromEmail":"dsimic@manjaro.org","sentAt":"2024-03-22T10:27:11Z","receivedAt":"2024-03-22T10:27:13Z","isPatch":false,"sender":{"key":"dsimic@manjaro.org","avatar":null},"body":"On 2024-03-22 10:56, Konstantin Khomoutov wrote:\n> On Fri, Mar 22, 2024 at 12:39:36PM +0300, Sergey Organov wrote:\n> \n>>>> I'd like to merge only certain files, or folders, from another\n>>>> branch.  What command or options should I be looking at to get\n>>>> this done?\n>>> \n>>> If you are using the verb \"merge\" in the way Git uses, then there is\n>>> *no* option to do so and that is very much deliberate, as allowing\n>>> such a operation will break your history.\n>> \n>> No, it won't break history. The merge commit *content* does not break\n>> *history* in any way. Path-limiting makes perfect sense when one is\n>> about to create merge commit content and knows in advance the exact \n>> set\n>> of paths the changes from which are to be included (or ignored).\n> \n> This reminded me of the \"disaster no. 2\" in the rant, arguably famous \n> at the\n> time [1], in particular:\n> \n> | One user of Tortoise Git would do a pull, have a merge conflict, \n> resolve the\n> | merge conflict, and then look carefully at his list of files to be \n> committed\n> | back when he was committing the results. There were lots of files \n> there, and\n> | he knew that the merge conflict only involved a couple of files. For \n> his\n> | commit, he unchecked all the other files changes that he was not \n> involved\n> | in, committed the results and pushed the commit.\n> \n> My understanding is that the OP actually wanted to create a similar \n> situation\n> consciously. It's quite possible that they intend to never merge the \n> results\n> back into \"the main line\" but anyway.\n> \n> The point is, the feature you're advocating is bound to be abused \n> exactly\n> through this \"this is my stuff, and there is the stuff I do not care \n> about\"\n> attitude.\n> \n> Having said that, I do not oppose these features (not that my opinion \n> should\n> have any weight; I'm just making things clear) as in the end the only \n> workable\n> solution to have decent quality of a project's content is \"gatekeeping\" \n> the\n> changes by the review process.\n> \n>  1. https://randyfay.com/content/avoiding-git-disasters-gory-story\n\nHere's a similar story...  A while back, when I used Subversion heavily,\nI (ab)used a lot its ability to perform partial updates to the working \ncopy,\ni.e. to run \"svn update <path>\".  It can be highly useful if used _VERY_\ncarefully, but it's also quite dangerous.  Like a chainsaw.\n"},{"id":"491240","messageId":"c3f144b20cef46de83f2282dd16a817f@atlas-elektronik.com","threadId":"61172","inReplyTo":"xmqqbk778oeb.fsf@gitster.g","subject":"RE: Merge selected files or folders","fromName":"","fromEmail":"stefan.naewe@atlas-elektronik.com","sentAt":"2024-03-22T12:24:04Z","receivedAt":"2024-03-22T12:25:16Z","isPatch":false,"sender":{"key":"stefan.naewe@gmail.com","avatar":"https://avatars.githubusercontent.com/u/4468?v=4"},"body":"Classification - ISMS: Offen | VS: OFFEN\n\n\n\n> -----Original Message-----\n> From: Junio C Hamano <gitster@pobox.com>\n> Sent: Thursday, March 21, 2024 6:51 PM\n> To: Richard Kerry <richard.kerry@eviden.com>\n> Cc: git@vger.kernel.org\n> Subject: Re: Merge selected files or folders\n> \n> Richard Kerry <richard.kerry@eviden.com> writes:\n> \n> > I'd like to merge only certain files, or folders, from another branch.\n> > What command or options should I be looking at to get this done?\n> \n> If you are using the verb \"merge\" in the way Git uses, then there is\n> *no* option to do so and that is very much deliberate, as allowing such a operation\n> will break your history.\n> \n> A \"merge\" commit in Git records the fact that *all* changes that were done in each\n> parent since the merged branches diverged have been considered and the tree\n> recorded by the merge commit is the result.  Hence, if you later change your mind\n> and \"merge\" other changes from the same branch, it will result in no change at all,\n> by definition.\n> \n> But if you are porting some changes made on another branch to the current\n> branch, and then planning to record the result as a regular single parent commit,\n> then there is no fundamental reason to forbid such an operation.  It is what cherry-\n> pick ought to be able to do, even though I do not think it accepts a pathspec to limit\n> currently.\n> \n> Assuming a history of this shape:\n> \n>       x---x---X (that other branch)\n>      /\n>     O---o---o---o---H\t(current branch)\n> \n> such a \"cherry-pick\" would essentially be applying all the changes lead to X since\n> the histories forked at O on top of H:\n> \n>     $ git checkout H\n>     $ O=$(git merge-base X H)\n>     $ git diff $O X | git apply\n>     $ git commit -m \"picked changes from branch X\"\n> \n> And if you want to limit the paths involved in the operation, the \"git diff\" step can be\n> given a <pathspec> to limit the changes that are ported.\n> \n>     $ git checkout H\n>     $ O=$(git merge-base X H)\n>     $ git diff $O X -- thisdir/ that/file | git apply\n>     $ git commit -m \"picked changes from branch X\"\n\nIsn't that the same as simply checking out the files/folders of \"that other branch\" and commiting the result ?\n\n$ git checkout X -- this/dir that/file\n$ git commit -m \"picked changes from branch X\"\n\nOr am I missing something ?\n\n> Teaching \"git cherry-pick\" to accept a pathspec and natively perform something like\n> the above is left as an exercise.\n\n\nThanks,\nStefan\n"},{"id":"491256","messageId":"xmqqa5mq18pu.fsf@gitster.g","threadId":"61172","inReplyTo":"c3f144b20cef46de83f2282dd16a817f@atlas-elektronik.com","subject":"Re: Merge selected files or folders","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-03-22T17:23:41Z","receivedAt":"2024-03-22T17:23:44Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"<stefan.naewe@atlas-elektronik.com> writes:\n\n>> Assuming a history of this shape:\n>> \n>>       x---x---X (that other branch)\n>>      /\n>>     O---o---o---o---H\t(current branch)\n>> ... \n>>     $ git checkout H\n>>     $ O=$(git merge-base X H)\n>>     $ git diff $O X -- thisdir/ that/file | git apply\n>>     $ git commit -m \"picked changes from branch X\"\n>\n> Isn't that the same as simply checking out the files/folders of\n> \"that other branch\" and commiting the result ?\n>\n> $ git checkout X -- this/dir that/file\n> $ git commit -m \"picked changes from branch X\"\n>\n> Or am I missing something ?\n\nYou would lose the changes the history O..H made to this/dir/** and\nthat/file if you did that, no?\n\n"}]}