git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: Different behaviour for --find-renames between git diff and git merge?

From
Elijah Newren <newren@gmail.com>
Date
Dec 16, 2025, 00:57 UTC
Message-ID
<CABPp-BH1qgQNHJzJZ05Ckru2PdYxRnWfQ3xVPrqGG5F56bX1aw@mail.gmail.com>
In-Reply-To
<d7135cd2-e577-4f96-8142-cd9c7cd6995d@gmail.com>

On Mon, Dec 15, 2025 at 6:02 AM Luca Balsanelli <lucabalsanelli@gmail.com> wrote:

>
> On 13/12/25 02:57, Elijah Newren wrote:
> > On Fri, Dec 12, 2025 at 10:06 AM Luca Balsanelli
> > <lucabalsanelli@gmail.com> wrote:
[...]
Show 6 quoted lines
> I would expect that `git merge branch` would detect a rename and the
> conflict resolved automatically. The 'ort' strategy (the default one),
> "can detect and handle merges involving renames." and the default
> similarity threshold is the same for `git diff` and `git merge`. I
> understand that the merge procedure involves finding a merge base, but
> still the rename should be detected between the two heads.

No, it should only detect renames between the merge-base and the heads. The merge machinery should not diff the two heads directly; that goes against how 3-way diff works.

[...]
Show 11 quoted lines
> Even though the `git diff master~1 master` doesn't detect the rename
> (the content changed too much compared to the empty file or one was
> empty (although it says it defaults to include empty files as rename
> source or destinarion)), the rename should be detected between the two
> heads, even when merging. I tried to read at 'git/diffcore-rename.c' but
> I'm not very good at C and it would require me a great effort to fully
> understand it.
>
> So, why `git merge branch` is not detecting the rename and not resolving
> the conflict automatically? Does it use a different diff machinery
> compared to `git diff`?

Merging never diffs the endpoints, and shouldn't either. It basically does two diffs, each from the merge-base to the end-point in question.

If you only diffed the endpoints, and one side renamed file A->B, how do you differentiate between A->B and B->A? In other words, you may know there was a rename, but you can't tell what it was renamed from and which filename should be the final one. You can only tell if you look at the merge-base and determine that the file started out named as A, and thus that B should be the final name.

If you only diffed the endpoints, and one side renamed file A->B, while the other side renamed A->C, you'd be misled into thinking this was a normal rename (you'd only see e.g. B->C) and be unaware of the conflict, which is problematic.

If you only diffed the endpoints, and one side renamed file A->B, while the other side renamed C->B, by diffing the endpoints you can't even tell there's a rename; you simply have a file named B that was totally rewritten. But it gets subtly worse in special cases that might really confuse end users: if they modified A or C on the sides of history that didn't rename those files, those changes would not be propagated and combined with the ultimate B, and they'd be left to pick up the pieces and try to combine things.

Further, it's just semantically wrong to diff the endpoints because of the underlying concept of a 3-way merge: If you were merging D & E and simply diffed D & E to do so, you won't know whether differing lines were added or removed by recent commits. For example, you might notice an "import" or "include" statement that one side has that the other doesn't. But did one side add that import statement? Or did the other side remove it? You can't tell by looking at the endpoints; you have to compare the endpoints to the merge-base to find out which things were added or removed. So, fundamentally, a 3-way merge thinks in terms of diffing the merge-base to the endpoints, not diffing the endpoints.

So, in summary, no, merge does not use a different diff machinery. You are just diffing the wrong commits to see what it sees. Combine that with the fact that you have a funny special case where both sides drastically change the file in a way where the new versions happen to be similar to each other while not similar to the original, causes the behavior you are seeing.

Previous: Luca BalsanelliNext: Luca Balsanelli
Message 4 of 6 in “Different behaviour for --find-renames between git diff and git merge?”
  1. Luca BalsanelliDec 12, 2025
  2. Elijah NewrenDec 13, 2025
  3. Luca BalsanelliDec 15, 2025
  4. Elijah NewrenDec 16, 2025
  5. Luca BalsanelliDec 16, 2025
  6. Elijah NewrenDec 16, 2025

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.