threads / bug / 63297

git merge bug report

Subject: git merge bug report

## tl;dr

4 messages between Apr 15, 2025 and Apr 15, 2025.

replies: 3people: 3as markdown or json

mu gsh· Apr 15, 2025, 12:23 UTC · lore
Dear Git Maintainers,

I would like to report a bug I encountered in Git during a merge operation. The method from one branch was merged into the wrong class, despite there being no reported conflict.

Git Version: git version 2.49.0 Operating System: Arch Linux

Description: When merging two commits involving changes to the same file, Git does not report a conflict, but the resulting merged file places a method in an unexpected class. This seems like a mismerge.

Steps to Reproduce You can reproduce the issue using the following shell script: ``` #!/bin/bash

set -e
# init in /tmp dir
rm -rf /tmp/git-merge-bug
mkdir -p /tmp/git-merge-bug && cd /tmp/git-merge-bug
git init
cat > models.py <<EOF
class User:
    name = "str"
class Product:
    id = 0
EOF
git add models.py
git commit -m "initial: User and Product class"
# feature1
git checkout -b feature
cat > models.py <<EOF
class User:
    name = "str"
    def user_method(self):
        return
class Product:
    id = 0
EOF
git commit -am "feature: add method to User"
# feature 2
git checkout master
cat > models.py <<EOF
class User:
    name = "str"
    bugger = "fix me"
class NoMethod:
    pass
class Product:
    id = 0
EOF
git commit -am "master: add field to User and new class"

git merge feature echo echo "==== merged, user_method into NoMethod class ====" cat models.py ```

Actual Result

After the merge, the user_method ends up inside the NoMethod class, which is incorrect and unexpected.

Please let me know if any additional information is needed. Thank you for your time and help.

Best regards,
gshmu
Junio C Hamano· Apr 15, 2025, 13:52 UTC · re: mu gsh · lore

Re: git merge bug report

mu gsh <yue937@gmail.com> writes:
Show 57 quoted lines
> cat > models.py <<EOF
> class User:
>     name = "str"
>
>
> class Product:
>     id = 0
> EOF
> git add models.py
> git commit -m "initial: User and Product class"
>
> # feature1
> git checkout -b feature
> cat > models.py <<EOF
> class User:
>     name = "str"
>
>     def user_method(self):
>         return
>
>
> class Product:
>     id = 0
> EOF
> git commit -am "feature: add method to User"
>
> # feature 2
> git checkout master
> cat > models.py <<EOF
> class User:
>     name = "str"
>     bugger = "fix me"
>
>
> class NoMethod:
>     pass
>
>
> class Product:
>     id = 0
> EOF
> git commit -am "master: add field to User and new class"
>
> git merge feature
> echo
> echo "==== merged, user_method into NoMethod class  ===="
> cat models.py
> ```
>
> Actual Result
>
> After the merge, the user_method ends up inside the NoMethod class,
> which is incorrect and unexpected.
>
>
> Please let me know if any additional information is needed. Thank you
> for your time and help.

I think this is very much expected, unfortunately. Git is language agnostic in the sense that it does not know the meaning of the contents of the file it is thrown at. With the merge, what it was asked to do is:

 - The other branch, "feature1", added three lines, an empty
   user_method() definition and a blank line around it, before
   lines that have 'class product:' and '  id = 0' (or after lines
   that have 'class User:' and '  name = str' followed by a blank
   line).
 - In the meantime, you added some stuff in feature2.
 - Please replay what the other branch did on top of what we have.

But after your feature2, the precontext lines that it can use as an anchor no longer exist (the blank line after 'class User:' and ' name = str' is gone). while the post context lines ("blank followed by 'class Product: followed by 'id = 0'") are still intact. Wiggling the added three lines there would be a more natural choice than having to deal with "bugger = 'fix me'" whose disposition is totally unclear to unthinking non-mind that is a mechanical merge machinery in Git.

Lucas Seiki Oshiro· Apr 15, 2025, 14:13 UTC · re: mu gsh · lore

Re: git merge bug report

Hi!
> I would like to report a bug I encountered in Git during a merge
> operation. The method from one branch was merged into the wrong class,
> despite there being no reported conflict.
Thanks for your script! I could reproduce this here!

When two branches changes the same plaintext file, Git tries to merge them based on their contents without taking into account the syntax. It is done using diff algorithms, which you can change using `-X diff-algorithm=<algorithm>`.

I tried the four algorithms available (minimal, histogram, myers and patience) and all of them produced the same result.

Sadly, they are not infallible and those mistakes may happen. There are other cases where it can happen. For example, imagine a Python class with only two methods and each branch deletes one of them. After merging, it will leave an empty class definition, which is not allowed in Python (unless you use `pass`). These algorithms are not aware of that, and they'll leave an invalid Python file.

Also note that they are not exactly wrong. They only do their work naively based on the information they have.

This way, it's always a good idea to check if the merge went well.
mu gsh· Apr 15, 2025, 16:20 UTC · re: Lucas Seiki Oshiro · lore

Re: git merge bug report

Hi!
focus on the feature 2, the two double empty lines, which one is the new one?
```
    bugger = "fix: the empty lines blow not the new added lines"
class NoMethod:
    pass

class Product ```

Should the second one be newly added? instead of the first

On Tue, 15 Apr 2025 at 22:13, Lucas Seiki Oshiro <lucasseikioshiro@gmail.com> wrote:

Show 28 quoted lines
>
> Hi!
>
> > I would like to report a bug I encountered in Git during a merge
> > operation. The method from one branch was merged into the wrong class,
> > despite there being no reported conflict.
>
> Thanks for your script! I could reproduce this here!
>
> When two branches changes the same plaintext file, Git tries to merge
> them based on their contents without taking into account the syntax.
> It is done using diff algorithms, which you can change using
> `-X diff-algorithm=<algorithm>`.
>
> I tried the four algorithms available (minimal, histogram, myers and
> patience) and all of them produced the same result.
>
> Sadly, they are not infallible and those mistakes may happen. There
> are other cases where it can happen. For example, imagine a Python
> class with only two methods and each branch deletes one of them.
> After merging, it will leave an empty class definition, which is not
> allowed in Python (unless you use `pass`). These algorithms are not
> aware of that, and they'll leave an invalid Python file.
>
> Also note that they are not exactly wrong. They only do their work
> naively based on the information they have.
>
> This way, it's always a good idea to check if the merge went well.

← back to recent threads