Re: git mv messed up file mapping if folders contain identical files
From: Bill Okara <hidden>
Date: 2016-06-15 23:08:29
Hi, On Fri, Feb 26, 2016 at 4:50 AM, SZEDER Gábor [off-list ref] wrote:
Please don't top-post on this list.
Sorry about that. Just learned what that means and why it is bad...
Subject: [PATCH] diffcore: fix iteration order of identical files during rename detection
If the two paths 'dir/A/file' and 'dir/B/file' have identical content
and the parent directory is renamed, e.g. 'git mv dir other-dir', then
diffcore reports the following exact renames:
renamed: dir/B/file -> other-dir/A/file
renamed: dir/A/file -> other-dir/B/file
While technically not wrong, this is confusing not only for the user,
but also for git commands that make decisions based on rename
information, e.g. 'git log --follow'.
This behavior is a side effect of commit v2.0.0-rc4~8^2~14
(diffcore-rename.c: simplify finding exact renames, 2013-11-14): the
hashmap storing sources returns entries from the same bucket, i.e.
sources matching the current destination, in LIFO order. Thus the
iteration first examines 'other-dir/A/file' and 'dir/B/file' and, upon
finding identical content and basename, reports an exact rename.
Restore the original behavior by reversing the order of filling the
hashmap with source entries.
Reported-by: Bill Okara <redacted>
Signed-off-by: SZEDER Gábor <redacted>
---
diffcore-rename.c | 6 ++++--
t/t4001-diff-rename.sh | 11 +++++++++++
2 files changed, 15 insertions(+), 2 deletions(-)quoted hunk ↗ jump to hunk
diff --git a/t/t4001-diff-rename.sh b/t/t4001-diff-rename.sh index 2f327b749588..ed90c6c6f984 100755 --- a/t/t4001-diff-rename.sh +++ b/t/t4001-diff-rename.sh@@ -77,6 +77,17 @@ test_expect_success 'favour same basenames even with minor differences' ' git show HEAD:path1 | sed "s/15/16/" > subdir/path1 && git status | test_i18ngrep "renamed: .*path1 -> subdir/path1"' +test_expect_success 'two files with same basename and same content' ' + git reset --hard && + mkdir -p dir/A dir/B && + cp path1 dir/A/file && + cp path1 dir/B/file && + git add dir && + git commit -m 2 && + git mv dir other-dir && + git status | test_i18ngrep "renamed: .*dir/A/file -> other-dir/A/file" +' + test_expect_success 'setup for many rename source candidates' ' git reset --hard && for i in 0 1 2 3 4 5 6 7 8 9; --2.7.2.410.g92cb358
Thank you very much for the fix and the detailed explanation! -Bill