]> git.ipfire.org Git - thirdparty/git.git/commitdiff
merge-ort: fix bug with renormalization and rename/delete conflicts
authorElijah Newren <newren@gmail.com>
Tue, 28 Dec 2021 00:20:46 +0000 (00:20 +0000)
committerJunio C Hamano <gitster@pobox.com>
Thu, 30 Dec 2021 18:40:26 +0000 (10:40 -0800)
Ever since commit a492d5331c ("merge-ort: ensure we consult df_conflict
and path_conflicts", 2021-06-30), when renormalization is active AND a
file is involved in a rename/delete conflict BUT the file is unmodified
(either before or after renormalization), merge-ort was running into an
assertion failure.  Prior to that commit (or if assertions were compiled
out), merge-ort would mis-merge instead, ignoring the rename/delete
conflict and just deleting the file.

Remove the assertions, fix the code appropriately, leave some good
comments in the code, and add a testcase for this situation.

Reported-by: Ralf Thielow <ralf.thielow@gmail.com>
Signed-off-by: Elijah Newren <newren@gmail.com>
Reviewed-by: Derrick Stolee <dstolee@microsoft.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
merge-ort.c
t/t6418-merge-text-auto.sh

index 0342f104836b69a7889b3fa686c7c359c27e5dd6..c319797021938a9df635c8db146ac6555331c7db 100644 (file)
@@ -3841,9 +3841,22 @@ static void process_entry(struct merge_options *opt,
                if (opt->renormalize &&
                    blob_unchanged(opt, &ci->stages[0], &ci->stages[side],
                                   path)) {
-                       ci->merged.is_null = 1;
-                       ci->merged.clean = 1;
-                       assert(!ci->df_conflict && !ci->path_conflict);
+                       if (!ci->path_conflict) {
+                               /*
+                                * Blob unchanged after renormalization, so
+                                * there's no modify/delete conflict after all;
+                                * we can just remove the file.
+                                */
+                               ci->merged.is_null = 1;
+                               ci->merged.clean = 1;
+                                /*
+                                 * file goes away => even if there was a
+                                 * directory/file conflict there isn't one now.
+                                 */
+                               ci->df_conflict = 0;
+                       } else {
+                               /* rename/delete, so conflict remains */
+                       }
                } else if (ci->path_conflict &&
                           oideq(&ci->stages[0].oid, &ci->stages[side].oid)) {
                        /*
index 1e0296dd17263e3d436dd4bc6d759d095ecccd50..41288a60ceb549295699f2efd9cb8e187d3e297b 100755 (executable)
@@ -204,4 +204,30 @@ test_expect_success 'Test delete/normalize conflict' '
        test_path_is_missing file
 '
 
+test_expect_success 'rename/delete vs. renormalization' '
+       git init subrepo &&
+       (
+               cd subrepo &&
+               echo foo >oldfile &&
+               git add oldfile &&
+               git commit -m original &&
+
+               git branch rename &&
+               git branch nuke &&
+
+               git checkout rename &&
+               git mv oldfile newfile &&
+               git commit -m renamed &&
+
+               git checkout nuke &&
+               git rm oldfile &&
+               git commit -m deleted &&
+
+               git checkout rename^0 &&
+               test_must_fail git -c merge.renormalize=true merge nuke >out &&
+
+               grep "rename/delete" out
+       )
+'
+
 test_done