{"thread":{"id":"62460","subject":"Question about merge & cherry pick","startedAt":"2024-11-06T20:40:31Z","lastAt":"2024-11-07T17:18:37Z","messageCount":5,"participants":["Julien Maurel","Johannes Sixt","brian m. carlson"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"506755","messageId":"711a0faa-6d82-48b6-819d-9ddbeda03f6a@maurel.me","threadId":"62460","inReplyTo":null,"subject":"Question about merge & cherry pick","fromName":"Julien Maurel","fromEmail":"julien@maurel.me","sentAt":"2024-11-06T20:24:35Z","receivedAt":"2024-11-06T20:40:31Z","isPatch":false,"sender":{"key":"julien@maurel.me","avatar":null},"body":"Hi,\nI detect a potential issue with usage of merge and cherry pick.\nI do a short script to reproduce my use case.\n From my point of view, after these operations, content on branch master \nand dev should be same with \"zZz\" on second line and \"eDe\" on last one.\nBut it's not the case on second line...\nI test the same thing with first commit on master, cherrypick on dev, \nsecond update on dev, merge dev on master, result is same.\nAnd I test to cherry pick second commit on master after final merge, \ncherry pick is ok and \"fix\" master content.\nCan you help me to understand if it's normal or not ?\n\nThe script :\nmkdir repo\ncd repo\n\n# Create a file and init 2 branches with same content\ngit init\necho -e \"aAa\\nzZz\\nqQq\\neEe\" > file\ngit add .\ngit commit -a -m \"init\"\ngit checkout -b dev\n\n# Update on dev\nsed -i \"s#Z#Y#\" file\ngit commit -a -m \"update\"\n\n# Cherrypick on master\ngit checkout master\ngit cherry-pick -x dev\n\n# Second update on dev\ngit checkout dev\nsed -i \"s#Y#Z#\" file\nsed -i \"s#E#D#\" file\ngit commit -a -m \"update that change second line as before first update \nand do another change\"\n\n# Merge on master\ngit checkout master\ngit merge dev --no-ff -m \"Merge\"\n\n# Display result\necho\necho\necho MASTER\ncat file\ngit checkout dev > /dev/null 2>&1\necho\necho DEV\ncat file\n\n\nThanks\n"},{"id":"506782","messageId":"eb367098-0c88-4bc6-b824-32ee6e6d273e@kdbg.org","threadId":"62460","inReplyTo":"711a0faa-6d82-48b6-819d-9ddbeda03f6a@maurel.me","subject":"Re: Question about merge & cherry pick","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2024-11-07T06:37:19Z","receivedAt":"2024-11-07T06:37:29Z","isPatch":false,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Am 06.11.24 um 21:24 schrieb Julien Maurel:\n> From my point of view, after these operations, content on branch master\n> and dev should be same with \"zZz\" on second line and \"eDe\" on last one.\n> But it's not the case on second line...\n\nThe behavior that you observe is as intended and not a bug.\n\nYou have this (consider each letter on its own line):\n\n          A Z Q E       initial commit\n         /       \\\n     A Y Q E      |     dev: Z -> Y\n        |         |\n        |     A Y Q E   master: cherry-pick Z -> Y\n        |         |\n     A Z Q D      |     dev: revert Y -> Z and change E -> D\n         \\        /\n          A Y Q D       merge\n\nYour expectation that the merge result is \"A Z Q D\" is wrong. Consider\nwhat happened on the dev branch (left) since the branches diverged:\nSince the change from Z to Y was reverted to Z, the only change that the\ndev side contributes to the merge is that of E to D. The master side, on\nthe other hand, contributes the change of Z to Y. So the total of the\nmerge must be Z to Y from the master side and E to D from the dev side,\nand that is what you get.\n\nA merge does not consider the individual changes on the branches, but\nonly the differences since the merge base. For the merge operation, the\nchange from Z to Y never happened on the dev side. The reversal of Y to\nZ is not visible for the merge and cannot contribute to the result.\n\n-- Hannes\n\n"},{"id":"506784","messageId":"a129e967-efba-48ba-b5a0-1abbb0af5c9d@maurel.me","threadId":"62460","inReplyTo":"eb367098-0c88-4bc6-b824-32ee6e6d273e@kdbg.org","subject":"Re: Question about merge & cherry pick","fromName":"Julien Maurel","fromEmail":"julien@maurel.me","sentAt":"2024-11-07T10:32:06Z","receivedAt":"2024-11-07T10:39:34Z","isPatch":false,"sender":{"key":"julien@maurel.me","avatar":null},"body":"Ok, I didn't have this vision about how merge is apply, thanks.\nThere is no option to merge by considering each commit individually ?\nRebase do it but not applicable in my case :)\nThanks.\n\nLe 07/11/2024 à 07:37, Johannes Sixt a écrit :\n> Am 06.11.24 um 21:24 schrieb Julien Maurel:\n>>  From my point of view, after these operations, content on branch master\n>> and dev should be same with \"zZz\" on second line and \"eDe\" on last one.\n>> But it's not the case on second line...\n> The behavior that you observe is as intended and not a bug.\n>\n> You have this (consider each letter on its own line):\n>\n>            A Z Q E       initial commit\n>           /       \\\n>       A Y Q E      |     dev: Z -> Y\n>          |         |\n>          |     A Y Q E   master: cherry-pick Z -> Y\n>          |         |\n>       A Z Q D      |     dev: revert Y -> Z and change E -> D\n>           \\        /\n>            A Y Q D       merge\n>\n> Your expectation that the merge result is \"A Z Q D\" is wrong. Consider\n> what happened on the dev branch (left) since the branches diverged:\n> Since the change from Z to Y was reverted to Z, the only change that the\n> dev side contributes to the merge is that of E to D. The master side, on\n> the other hand, contributes the change of Z to Y. So the total of the\n> merge must be Z to Y from the master side and E to D from the dev side,\n> and that is what you get.\n>\n> A merge does not consider the individual changes on the branches, but\n> only the differences since the merge base. For the merge operation, the\n> change from Z to Y never happened on the dev side. The reversal of Y to\n> Z is not visible for the merge and cannot contribute to the result.\n>\n> -- Hannes\n>\n\n"},{"id":"506791","messageId":"ZyysPeBRXvTAxLVf@tapette.crustytoothpaste.net","threadId":"62460","inReplyTo":"a129e967-efba-48ba-b5a0-1abbb0af5c9d@maurel.me","subject":"Re: Question about merge & cherry pick","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2024-11-07T12:02:05Z","receivedAt":"2024-11-07T12:02:07Z","isPatch":false,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On 2024-11-07 at 10:32:06, Julien Maurel wrote:\n> Ok, I didn't have this vision about how merge is apply, thanks.\n> There is no option to merge by considering each commit individually ?\n> Rebase do it but not applicable in my case :)\n\nThere's no way to do a merge commit-by commit.  The recommendation is to\ndo a rebase, since it essentially does a commit-by-commit merge under the\nhood (due to using the merge machinery).  The title of the FAQ entry at\n[0] doesn't perfectly describe your case, but it does sort of explain it\nand it explains how the merge and rebase machinery works.\n\n[0] https://git-scm.com/docs/gitfaq#merge-two-revert-one\n-- \nbrian m. carlson (they/them or he/him)\nToronto, Ontario, CA\n"},{"id":"506807","messageId":"eb3a25c0-7f43-4811-a9ad-0388f395b26e@kdbg.org","threadId":"62460","inReplyTo":"a129e967-efba-48ba-b5a0-1abbb0af5c9d@maurel.me","subject":"Re: Question about merge & cherry pick","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2024-11-07T17:18:25Z","receivedAt":"2024-11-07T17:18:37Z","isPatch":false,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Am 07.11.24 um 11:32 schrieb Julien Maurel:\n> Le 07/11/2024 à 07:37, Johannes Sixt a écrit :\n>> A merge does not consider the individual changes on the branches, but\n>> only the differences since the merge base. For the merge operation, the\n>> change from Z to Y never happened on the dev side. The reversal of Y to\n>> Z is not visible for the merge and cannot contribute to the result.\n> \n> Ok, I didn't have this vision about how merge is apply, thanks.\n> There is no option to merge by considering each commit individually ?\n> Rebase do it but not applicable in my case :)\n\nYou can merge the dev branch in two steps:\n\n          A Z Q E        initial commit\n          /      \\\n      A Y Q E     |      dev: Z -> Y\n         |\\       |\n         | \\   A Y Q E   master: cherry-pick Z -> Y\n         |  \\     |\n         |   A Y Q E     master: merge dev\n         |        |\n      A Z Q D     |      dev: revert Y -> Z and change E -> D\n          \\      /\n          A Z Q D        merge again\n\nThe merge of dev into master changes the merge base of the final merge:\nit is the second commit in the diagram. Now there is no contribution to\nthe merge from the master branch anymore, because its tip is identical\nto the merge base, and both changes made in the second commit on dev are\nvisible and contribute to the merge result.\n\n-- Hannes\n\n"}]}