threads / discuss / 62460

Question about merge & cherry pick

Subject: Question about merge & cherry pick

## tl;dr

5 messages between Nov 6, 2024 and Nov 7, 2024.

replies: 4people: 3as markdown or json

Julien Maurel· Nov 6, 2024, 20:24 UTC · lore
Hi,
I detect a potential issue with usage of merge and cherry pick.
I do a short script to reproduce my use case.
 From my point of view, after these operations, content on branch master 
and dev should be same with "zZz" on second line and "eDe" on last one.
But it's not the case on second line...
I test the same thing with first commit on master, cherrypick on dev, 
second update on dev, merge dev on master, result is same.
And I test to cherry pick second commit on master after final merge, 
cherry pick is ok and "fix" master content.
Can you help me to understand if it's normal or not ?

The script : mkdir repo cd repo

# Create a file and init 2 branches with same content git init echo -e "aAa\nzZz\nqQq\neEe" > file git add . git commit -a -m "init" git checkout -b dev

# Update on dev sed -i "s#Z#Y#" file git commit -a -m "update"

# Cherrypick on master git checkout master git cherry-pick -x dev

# Second update on dev git checkout dev sed -i "s#Y#Z#" file sed -i "s#E#D#" file git commit -a -m "update that change second line as before first update and do another change"

# Merge on master git checkout master git merge dev --no-ff -m "Merge"

# Display result echo echo echo MASTER cat file git checkout dev > /dev/null 2>&1 echo echo DEV cat file

Thanks
Johannes Sixt· Nov 7, 2024, 06:37 UTC · re: Julien Maurel · lore

Re: Question about merge & cherry pick

Am 06.11.24 um 21:24 schrieb Julien Maurel:
> From my point of view, after these operations, content on branch master
> and dev should be same with "zZz" on second line and "eDe" on last one.
> But it's not the case on second line...
The behavior that you observe is as intended and not a bug.
You have this (consider each letter on its own line):
          A Z Q E       initial commit
         /       \
     A Y Q E      |     dev: Z -> Y
        |         |
        |     A Y Q E   master: cherry-pick Z -> Y
        |         |
     A Z Q D      |     dev: revert Y -> Z and change E -> D
         \        /
          A Y Q D       merge

Your expectation that the merge result is "A Z Q D" is wrong. Consider what happened on the dev branch (left) since the branches diverged: Since the change from Z to Y was reverted to Z, the only change that the dev side contributes to the merge is that of E to D. The master side, on the other hand, contributes the change of Z to Y. So the total of the merge must be Z to Y from the master side and E to D from the dev side, and that is what you get.

A merge does not consider the individual changes on the branches, but only the differences since the merge base. For the merge operation, the change from Z to Y never happened on the dev side. The reversal of Y to Z is not visible for the merge and cannot contribute to the result.

-- Hannes
Julien Maurel· Nov 7, 2024, 10:32 UTC · re: Johannes Sixt · lore

Re: Question about merge & cherry pick

Ok, I didn't have this vision about how merge is apply, thanks. There is no option to merge by considering each commit individually ? Rebase do it but not applicable in my case :) Thanks.

Le 07/11/2024 à 07:37, Johannes Sixt a écrit :
Show 33 quoted lines
> Am 06.11.24 um 21:24 schrieb Julien Maurel:
>>  From my point of view, after these operations, content on branch master
>> and dev should be same with "zZz" on second line and "eDe" on last one.
>> But it's not the case on second line...
> The behavior that you observe is as intended and not a bug.
>
> You have this (consider each letter on its own line):
>
>            A Z Q E       initial commit
>           /       \
>       A Y Q E      |     dev: Z -> Y
>          |         |
>          |     A Y Q E   master: cherry-pick Z -> Y
>          |         |
>       A Z Q D      |     dev: revert Y -> Z and change E -> D
>           \        /
>            A Y Q D       merge
>
> Your expectation that the merge result is "A Z Q D" is wrong. Consider
> what happened on the dev branch (left) since the branches diverged:
> Since the change from Z to Y was reverted to Z, the only change that the
> dev side contributes to the merge is that of E to D. The master side, on
> the other hand, contributes the change of Z to Y. So the total of the
> merge must be Z to Y from the master side and E to D from the dev side,
> and that is what you get.
>
> A merge does not consider the individual changes on the branches, but
> only the differences since the merge base. For the merge operation, the
> change from Z to Y never happened on the dev side. The reversal of Y to
> Z is not visible for the merge and cannot contribute to the result.
>
> -- Hannes
>
brian m. carlson· Nov 7, 2024, 12:02 UTC · re: Julien Maurel · lore

Re: Question about merge & cherry pick

On 2024-11-07 at 10:32:06, Julien Maurel wrote:
> Ok, I didn't have this vision about how merge is apply, thanks.
> There is no option to merge by considering each commit individually ?
> Rebase do it but not applicable in my case :)

There's no way to do a merge commit-by commit. The recommendation is to do a rebase, since it essentially does a commit-by-commit merge under the hood (due to using the merge machinery). The title of the FAQ entry at [0] doesn't perfectly describe your case, but it does sort of explain it and it explains how the merge and rebase machinery works.

[0] https://git-scm.com/docs/gitfaq#merge-two-revert-one
-- 
brian m. carlson (they/them or he/him)
Toronto, Ontario, CA
Johannes Sixt· Nov 7, 2024, 17:18 UTC · re: Julien Maurel · lore

Re: Question about merge & cherry pick

Am 07.11.24 um 11:32 schrieb Julien Maurel:
Show 9 quoted lines
> Le 07/11/2024 à 07:37, Johannes Sixt a écrit :
>> A merge does not consider the individual changes on the branches, but
>> only the differences since the merge base. For the merge operation, the
>> change from Z to Y never happened on the dev side. The reversal of Y to
>> Z is not visible for the merge and cannot contribute to the result.
> 
> Ok, I didn't have this vision about how merge is apply, thanks.
> There is no option to merge by considering each commit individually ?
> Rebase do it but not applicable in my case :)
You can merge the dev branch in two steps:
          A Z Q E        initial commit
          /      \
      A Y Q E     |      dev: Z -> Y
         |\       |
         | \   A Y Q E   master: cherry-pick Z -> Y
         |  \     |
         |   A Y Q E     master: merge dev
         |        |
      A Z Q D     |      dev: revert Y -> Z and change E -> D
          \      /
          A Z Q D        merge again

The merge of dev into master changes the merge base of the final merge: it is the second commit in the diagram. Now there is no contribution to the merge from the master branch anymore, because its tip is identical to the merge base, and both changes made in the second commit on dev are visible and contribute to the merge result.

-- Hannes

← back to recent threads