@@ -279,4 +279,177 @@ test_expect_success 'recursive merge with submodule' '
279279 grep "$(cat expect3)" actual > /dev/null)
280280'
281281
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+
282455test_done
0 commit comments