@@ -279,4 +279,177 @@ test_expect_success 'recursive merge with submodule' '
279
279
grep "$(cat expect3)" actual > /dev/null)
280
280
'
281
281
282
+ # File/submodule conflict
283
+ # Commit O: <empty>
284
+ # Commit A: path (submodule)
285
+ # Commit B: path
286
+ # Expected: path/ is submodule and file contents for B's path are somewhere
287
+
288
+ test_expect_success ' setup file/submodule conflict' '
289
+ test_create_repo file-submodule &&
290
+ (
291
+ cd file-submodule &&
292
+
293
+ git commit --allow-empty -m O &&
294
+
295
+ git branch A &&
296
+ git branch B &&
297
+
298
+ git checkout B &&
299
+ echo content >path &&
300
+ git add path &&
301
+ git commit -m B &&
302
+
303
+ git checkout A &&
304
+ test_create_repo path &&
305
+ test_commit -C path world &&
306
+ git submodule add ./path &&
307
+ git commit -m A
308
+ )
309
+ '
310
+
311
+ test_expect_failure ' file/submodule conflict' '
312
+ test_when_finished "git -C file-submodule reset --hard" &&
313
+ (
314
+ cd file-submodule &&
315
+
316
+ git checkout A^0 &&
317
+ test_must_fail git merge B^0 &&
318
+
319
+ git ls-files -s >out &&
320
+ test_line_count = 3 out &&
321
+ git ls-files -u >out &&
322
+ test_line_count = 2 out &&
323
+
324
+ # path/ is still a submodule
325
+ test_path_is_dir path/.git &&
326
+
327
+ # There is a submodule at "path", so B:path cannot be written
328
+ # there. We expect it to be written somewhere in the same
329
+ # directory, though, so just grep for its content in all
330
+ # files, and ignore "grep: path: Is a directory" message
331
+ echo Checking if contents from B:path showed up anywhere &&
332
+ grep -q content * 2>/dev/null
333
+ )
334
+ '
335
+
336
+ test_expect_success ' file/submodule conflict; merge --abort works afterward' '
337
+ test_when_finished "git -C file-submodule reset --hard" &&
338
+ (
339
+ cd file-submodule &&
340
+
341
+ git checkout A^0 &&
342
+ test_must_fail git merge B^0 >out 2>err &&
343
+
344
+ test_path_is_file .git/MERGE_HEAD &&
345
+ git merge --abort
346
+ )
347
+ '
348
+
349
+ # Directory/submodule conflict
350
+ # Commit O: <empty>
351
+ # Commit A: path (submodule), with sole tracked file named 'world'
352
+ # Commit B1: path/file
353
+ # Commit B2: path/world
354
+ #
355
+ # Expected from merge of A & B1:
356
+ # Contents under path/ from commit B1 are renamed elsewhere; we do not
357
+ # want to write files from one of our tracked directories into a submodule
358
+ #
359
+ # Expected from merge of A & B2:
360
+ # Similar to last merge, but with a slight twist: we don't want paths
361
+ # under the submodule to be treated as untracked or in the way.
362
+
363
+ test_expect_success ' setup directory/submodule conflict' '
364
+ test_create_repo directory-submodule &&
365
+ (
366
+ cd directory-submodule &&
367
+
368
+ git commit --allow-empty -m O &&
369
+
370
+ git branch A &&
371
+ git branch B1 &&
372
+ git branch B2 &&
373
+
374
+ git checkout B1 &&
375
+ mkdir path &&
376
+ echo contents >path/file &&
377
+ git add path/file &&
378
+ git commit -m B1 &&
379
+
380
+ git checkout B2 &&
381
+ mkdir path &&
382
+ echo contents >path/world &&
383
+ git add path/world &&
384
+ git commit -m B2 &&
385
+
386
+ git checkout A &&
387
+ test_create_repo path &&
388
+ test_commit -C path hello world &&
389
+ git submodule add ./path &&
390
+ git commit -m A
391
+ )
392
+ '
393
+
394
+ test_expect_failure ' directory/submodule conflict; keep submodule clean' '
395
+ test_when_finished "git -C directory-submodule reset --hard" &&
396
+ (
397
+ cd directory-submodule &&
398
+
399
+ git checkout A^0 &&
400
+ test_must_fail git merge B1^0 &&
401
+
402
+ git ls-files -s >out &&
403
+ test_line_count = 3 out &&
404
+ git ls-files -u >out &&
405
+ test_line_count = 1 out &&
406
+
407
+ # path/ is still a submodule
408
+ test_path_is_dir path/.git &&
409
+
410
+ echo Checking if contents from B1:path/file showed up &&
411
+ # Would rather use grep -r, but that is GNU extension...
412
+ git ls-files -co | xargs grep -q contents 2>/dev/null &&
413
+
414
+ # However, B1:path/file should NOT have shown up at path/file,
415
+ # because we should not write into the submodule
416
+ test_path_is_missing path/file
417
+ )
418
+ '
419
+
420
+ test_expect_failure ' directory/submodule conflict; should not treat submodule files as untracked or in the way' '
421
+ test_when_finished "git -C directory-submodule/path reset --hard" &&
422
+ test_when_finished "git -C directory-submodule reset --hard" &&
423
+ (
424
+ cd directory-submodule &&
425
+
426
+ git checkout A^0 &&
427
+ test_must_fail git merge B2^0 >out 2>err &&
428
+
429
+ # We do not want files within the submodule to prevent the
430
+ # merge from starting; we should not be writing to such paths
431
+ # anyway.
432
+ test_i18ngrep ! "refusing to lose untracked file at" err
433
+ )
434
+ '
435
+
436
+ test_expect_failure ' directory/submodule conflict; merge --abort works afterward' '
437
+ test_when_finished "git -C directory-submodule/path reset --hard" &&
438
+ test_when_finished "git -C directory-submodule reset --hard" &&
439
+ (
440
+ cd directory-submodule &&
441
+
442
+ git checkout A^0 &&
443
+ test_must_fail git merge B2^0 &&
444
+ test_path_is_file .git/MERGE_HEAD &&
445
+
446
+ # merge --abort should succeed, should clear .git/MERGE_HEAD,
447
+ # and should not leave behind any conflicted files
448
+ git merge --abort &&
449
+ test_path_is_missing .git/MERGE_HEAD &&
450
+ git ls-files -u >conflicts &&
451
+ test_must_be_empty conflicts
452
+ )
453
+ '
454
+
282
455
test_done
0 commit comments