@@ -1277,20 +1277,114 @@ test_expect_success '6a: Tricky rename/delete' '
1277
1277
)
1278
1278
'
1279
1279
1280
- # Testcase 6b, Same rename done on both sides
1280
+ # Testcase 6b1, Same rename done on both sides
1281
+ # (Related to testcase 6b2 and 8e)
1282
+ # Commit O: z/{b,c,d,e}
1283
+ # Commit A: y/{b,c,d}, x/e
1284
+ # Commit B: y/{b,c,d}, z/{e,f}
1285
+ # Expected: y/{b,c,d,f}, x/e
1286
+ # Note: Directory rename detection says A renamed z/ -> y/ (3 paths renamed
1287
+ # to y/ and only 1 renamed to x/), therefore the new file 'z/f' in B
1288
+ # should be moved to 'y/f'.
1289
+ #
1290
+ # This is a bit of an edge case where any behavior might surprise users,
1291
+ # whether that is treating A as renaming z/ -> y/, treating A as renaming
1292
+ # z/ -> x/, or treating A as not doing any directory rename. However, I
1293
+ # think this answer is the least confusing and most consistent with the
1294
+ # rules elsewhere.
1295
+ #
1296
+ # A note about z/ -> x/, since it may not be clear how that could come
1297
+ # about: If we were to ignore files renamed by both sides
1298
+ # (i.e. z/{b,c,d}), as directory rename detection did in git-2.18 thru
1299
+ # at least git-2.28, then we would note there are no renames from z/ to
1300
+ # y/ and one rename from z/ to x/ and thus come to the conclusion that
1301
+ # A renamed z/ -> x/. This seems more confusing for end users than a
1302
+ # rename of z/ to y/, it makes directory rename detection behavior
1303
+ # harder for them to predict. As such, we modified the rule, changed
1304
+ # the behavior on testcases 6b2 and 8e, and introduced this 6b1 testcase.
1305
+
1306
+ test_setup_6b1 () {
1307
+ test_create_repo 6b1 &&
1308
+ (
1309
+ cd 6b1 &&
1310
+
1311
+ mkdir z &&
1312
+ echo b > z/b &&
1313
+ echo c > z/c &&
1314
+ echo d > z/d &&
1315
+ echo e > z/e &&
1316
+ git add z &&
1317
+ test_tick &&
1318
+ git commit -m " O" &&
1319
+
1320
+ git branch O &&
1321
+ git branch A &&
1322
+ git branch B &&
1323
+
1324
+ git checkout A &&
1325
+ git mv z y &&
1326
+ mkdir x &&
1327
+ git mv y/e x/e &&
1328
+ test_tick &&
1329
+ git commit -m " A" &&
1330
+
1331
+ git checkout B &&
1332
+ git mv z y &&
1333
+ mkdir z &&
1334
+ git mv y/e z/e &&
1335
+ echo f > z/f &&
1336
+ git add z/f &&
1337
+ test_tick &&
1338
+ git commit -m " B"
1339
+ )
1340
+ }
1341
+
1342
+ test_expect_failure ' 6b1: Same renames done on both sides, plus another rename' '
1343
+ test_setup_6b1 &&
1344
+ (
1345
+ cd 6b1 &&
1346
+
1347
+ git checkout A^0 &&
1348
+
1349
+ git -c merge.directoryRenames=true merge -s recursive B^0 &&
1350
+
1351
+ git ls-files -s >out &&
1352
+ test_line_count = 5 out &&
1353
+ git ls-files -u >out &&
1354
+ test_line_count = 0 out &&
1355
+ git ls-files -o >out &&
1356
+ test_line_count = 1 out &&
1357
+
1358
+ git rev-parse >actual \
1359
+ HEAD:y/b HEAD:y/c HEAD:y/d HEAD:x/e HEAD:y/f &&
1360
+ git rev-parse >expect \
1361
+ O:z/b O:z/c O:z/d O:z/e B:z/f &&
1362
+ test_cmp expect actual
1363
+ )
1364
+ '
1365
+
1366
+ # Testcase 6b2, Same rename done on both sides
1281
1367
# (Related to testcases 6c and 8e)
1282
1368
# Commit O: z/{b,c}
1283
1369
# Commit A: y/{b,c}
1284
1370
# Commit B: y/{b,c}, z/d
1285
- # Expected: y/{b,c}, z/d
1286
- # Note: If we did directory rename detection here, we'd move z/d into y/,
1287
- # but B did that rename and still decided to put the file into z/,
1288
- # so we probably shouldn't apply directory rename detection for it.
1289
-
1290
- test_setup_6b () {
1291
- test_create_repo 6b &&
1371
+ # Expected: y/{b,c,d}
1372
+ # Alternate: y/{b,c}, z/d
1373
+ # Note: Directory rename detection says A renamed z/ -> y/, therefore the new
1374
+ # file 'z/d' in B should be moved to 'y/d'.
1375
+ #
1376
+ # We could potentially ignore the renames of z/{b,c} on side A since
1377
+ # those were renamed on both sides. However, it's a bit of a corner
1378
+ # case because what if there was also a z/e that side A moved to x/e
1379
+ # and side B left alone? If we used the "ignore renames done on both
1380
+ # sides" logic, then we'd compute that A renamed z/ -> x/, and move
1381
+ # z/d to x/d. That seems more surprising and uglier than allowing
1382
+ # the z/ -> y/ rename.
1383
+
1384
+ test_setup_6b2 () {
1385
+ test_create_repo 6b2 &&
1292
1386
(
1293
- cd 6b &&
1387
+ cd 6b2 &&
1294
1388
1295
1389
mkdir z &&
1296
1390
echo b > z/b &&
@@ -1318,10 +1412,10 @@ test_setup_6b () {
1318
1412
)
1319
1413
}
1320
1414
1321
- test_expect_success ' 6b : Same rename done on both sides' '
1322
- test_setup_6b &&
1415
+ test_expect_failure ' 6b2 : Same rename done on both sides' '
1416
+ test_setup_6b2 &&
1323
1417
(
1324
- cd 6b &&
1418
+ cd 6b2 &&
1325
1419
1326
1420
git checkout A^0 &&
1327
1421
@@ -1335,15 +1429,15 @@ test_expect_success '6b: Same rename done on both sides' '
1335
1429
test_line_count = 1 out &&
1336
1430
1337
1431
git rev-parse >actual \
1338
- HEAD:y/b HEAD:y/c HEAD:z /d &&
1432
+ HEAD:y/b HEAD:y/c HEAD:y /d &&
1339
1433
git rev-parse >expect \
1340
1434
O:z/b O:z/c B:z/d &&
1341
1435
test_cmp expect actual
1342
1436
)
1343
1437
'
1344
1438
1345
1439
# Testcase 6c, Rename only done on same side
1346
- # (Related to testcases 6b and 8e)
1440
+ # (Related to testcases 6b1, 6b2, and 8e)
1347
1441
# Commit O: z/{b,c}
1348
1442
# Commit A: z/{b,c} (no change)
1349
1443
# Commit B: y/{b,c}, z/d
@@ -2269,14 +2363,22 @@ test_expect_success '8d: rename/delete...or not?' '
2269
2363
# Notes: In commit A, directory z got renamed to y. In commit B, directory z
2270
2364
# did NOT get renamed; the directory is still present; instead it is
2271
2365
# considered to have just renamed a subset of paths in directory z
2272
- # elsewhere. However, this is much like testcase 6b (where commit B
2273
- # moves all the original paths out of z/ but opted to keep d
2274
- # within z/). This makes it hard to judge where d should end up.
2366
+ # elsewhere. This is much like testcase 6b2 (where commit B moves all
2367
+ # the original paths out of z/ but opted to keep d within z/).
2368
+ #
2369
+ # It was not clear in the past what should be done with this testcase;
2370
+ # in fact, I noted that I "just picked one" previously. However,
2371
+ # following the new logic for testcase 6b2, we should take the rename
2372
+ # and move z/d to y/d.
2275
2373
#
2276
- # It's possible that users would get confused about this, but what
2277
- # should we do instead? It's not at all clear to me whether z/d or
2278
- # y/d or something else is a better resolution here, and other cases
2279
- # start getting really tricky, so I just picked one.
2374
+ # 6b1, 6b2, and this case are definitely somewhat fuzzy in terms of
2375
+ # whether they are optimal for end users, but (a) the default for
2376
+ # directory rename detection is to mark these all as conflicts
2377
+ # anyway, (b) it feels like this is less prone to higher order corner
2378
+ # case confusion, and (c) the current algorithm requires less global
2379
+ # knowledge (i.e. less coupling in the algorithm between renames done
2380
+ # on both sides) which thus means users are better able to predict
2381
+ # the behavior, and predict it without computing as many details.
2280
2382
2281
2383
test_setup_8e () {
2282
2384
test_create_repo 8e &&
0 commit comments