]> git.ipfire.org Git - thirdparty/git.git/blame - t/t6437-submodule-merge.sh
t64xx: convert 'test_create_repo' to 'git init'
[thirdparty/git.git] / t / t6437-submodule-merge.sh
CommitLineData
f37ae35e
CB
1#!/bin/sh
2
3test_description='merging with submodules'
4
5902f5f4 5GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
334afbc7
JS
6export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
7
155b517d
JT
8GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB=1
9export GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB
10
f37ae35e 11. ./test-lib.sh
aa2faac0 12. "$TEST_DIRECTORY"/lib-merge.sh
f37ae35e
CB
13
14#
15# history
16#
17# a --- c
18# / \ /
19# root X
20# \ / \
21# b --- d
22#
23
24test_expect_success setup '
25
26 mkdir sub &&
27 (cd sub &&
28 git init &&
29 echo original > file &&
30 git add file &&
31 test_tick &&
32 git commit -m sub-root) &&
33 git add sub &&
34 test_tick &&
35 git commit -m root &&
36
5902f5f4 37 git checkout -b a main &&
f37ae35e
CB
38 (cd sub &&
39 echo A > file &&
40 git add file &&
41 test_tick &&
42 git commit -m sub-a) &&
43 git add sub &&
44 test_tick &&
45 git commit -m a &&
46
5902f5f4 47 git checkout -b b main &&
f37ae35e
CB
48 (cd sub &&
49 echo B > file &&
50 git add file &&
51 test_tick &&
52 git commit -m sub-b) &&
53 git add sub &&
54 test_tick &&
420432d4 55 git commit -m b &&
f37ae35e
CB
56
57 git checkout -b c a &&
58 git merge -s ours b &&
59
60 git checkout -b d b &&
61 git merge -s ours a
62'
63
68d03e4a
HV
64# History setup
65#
313ee0d6
NMC
66# b
67# / \
68# init -- a d
69# \ \ /
70# g c
68d03e4a
HV
71#
72# a in the main repository records to sub-a in the submodule and
73# analogous b and c. d should be automatically found by merging c into
74# b in the main repository.
75test_expect_success 'setup for merge search' '
76 mkdir merge-search &&
1e284763 77 (cd merge-search &&
68d03e4a
HV
78 git init &&
79 mkdir sub &&
80 (cd sub &&
81 git init &&
82 echo "file-a" > file-a &&
83 git add file-a &&
84 git commit -m "sub-a" &&
85 git branch sub-a) &&
313ee0d6
NMC
86 git commit --allow-empty -m init &&
87 git branch init &&
68d03e4a
HV
88 git add sub &&
89 git commit -m "a" &&
90 git branch a &&
91
92 git checkout -b b &&
93 (cd sub &&
94 git checkout -b sub-b &&
95 echo "file-b" > file-b &&
96 git add file-b &&
97 git commit -m "sub-b") &&
98 git commit -a -m "b" &&
99
100 git checkout -b c a &&
101 (cd sub &&
102 git checkout -b sub-c sub-a &&
103 echo "file-c" > file-c &&
104 git add file-c &&
105 git commit -m "sub-c") &&
4057523a
CW
106 git commit -a -m "c")
107'
68d03e4a 108
4057523a
CW
109test_expect_success 'merging should conflict for non fast-forward' '
110 test_when_finished "git -C merge-search reset --hard" &&
111 (cd merge-search &&
112 git checkout -b test-nonforward-a b &&
113 if test "$GIT_TEST_MERGE_ALGORITHM" = ort
114 then
115 test_must_fail git merge c >actual &&
116 sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short sub-c)" &&
117 grep "$sub_expect" actual
118 else
119 test_must_fail git merge c 2> actual
120 fi)
121'
122
123test_expect_success 'finish setup for merge-search' '
124 (cd merge-search &&
68d03e4a
HV
125 git checkout -b d a &&
126 (cd sub &&
127 git checkout -b sub-d sub-b &&
128 git merge sub-c) &&
129 git commit -a -m "d" &&
313ee0d6
NMC
130 git branch test b &&
131
132 git checkout -b g init &&
133 (cd sub &&
134 git checkout -b sub-g sub-c) &&
135 git add sub &&
136 git commit -a -m "g")
68d03e4a
HV
137'
138
139test_expect_success 'merge with one side as a fast-forward of the other' '
140 (cd merge-search &&
141 git checkout -b test-forward b &&
142 git merge d &&
143 git ls-tree test-forward sub | cut -f1 | cut -f3 -d" " > actual &&
144 (cd sub &&
145 git rev-parse sub-d > ../expect) &&
9c5b2fab 146 test_cmp expect actual)
68d03e4a
HV
147'
148
4057523a 149test_expect_success 'merging should conflict for non fast-forward (resolution exists)' '
68d03e4a 150 (cd merge-search &&
4057523a 151 git checkout -b test-nonforward-b b &&
68d03e4a 152 (cd sub &&
a4040cfa 153 git rev-parse --short sub-d > ../expect) &&
c8c35f6a
EN
154 if test "$GIT_TEST_MERGE_ALGORITHM" = ort
155 then
4057523a
CW
156 test_must_fail git merge c >actual &&
157 sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short sub-c)" &&
158 grep "$sub_expect" actual
c8c35f6a
EN
159 else
160 test_must_fail git merge c 2> actual
161 fi &&
68d03e4a
HV
162 grep $(cat expect) actual > /dev/null &&
163 git reset --hard)
164'
165
166test_expect_success 'merging should fail for ambiguous common parent' '
1e284763 167 (cd merge-search &&
68d03e4a
HV
168 git checkout -b test-ambiguous b &&
169 (cd sub &&
170 git checkout -b ambiguous sub-b &&
171 git merge sub-c &&
c8c35f6a
EN
172 if test "$GIT_TEST_MERGE_ALGORITHM" = ort
173 then
174 git rev-parse --short sub-d >../expect1 &&
175 git rev-parse --short ambiguous >../expect2
176 else
177 git rev-parse sub-d > ../expect1 &&
178 git rev-parse ambiguous > ../expect2
179 fi
180 ) &&
181 if test "$GIT_TEST_MERGE_ALGORITHM" = ort
182 then
4057523a
CW
183 test_must_fail git merge c >actual &&
184 sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short sub-c)" &&
185 grep "$sub_expect" actual
c8c35f6a
EN
186 else
187 test_must_fail git merge c 2> actual
188 fi &&
68d03e4a
HV
189 grep $(cat expect1) actual > /dev/null &&
190 grep $(cat expect2) actual > /dev/null &&
1e284763 191 git reset --hard)
68d03e4a
HV
192'
193
194# in a situation like this
195#
196# submodule tree:
197#
198# sub-a --- sub-b --- sub-d
199#
200# main tree:
201#
202# e (sub-a)
203# /
204# bb (sub-b)
205# \
206# f (sub-d)
207#
208# A merge between e and f should fail because one of the submodule
209# commits (sub-a) does not descend from the submodule merge-base (sub-b).
210#
211test_expect_success 'merging should fail for changes that are backwards' '
1e284763 212 (cd merge-search &&
68d03e4a
HV
213 git checkout -b bb a &&
214 (cd sub &&
215 git checkout sub-b) &&
216 git commit -a -m "bb" &&
217
218 git checkout -b e bb &&
219 (cd sub &&
220 git checkout sub-a) &&
221 git commit -a -m "e" &&
222
223 git checkout -b f bb &&
224 (cd sub &&
225 git checkout sub-d) &&
226 git commit -a -m "f" &&
f37ae35e 227
68d03e4a 228 git checkout -b test-backward e &&
4057523a
CW
229 test_must_fail git merge f >actual &&
230 if test "$GIT_TEST_MERGE_ALGORITHM" = ort
231 then
232 sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short sub-d)" &&
233 grep "$sub_expect" actual
234 fi)
f37ae35e
CB
235'
236
313ee0d6
NMC
237
238# Check that the conflicting submodule is detected when it is
239# in the common ancestor. status should be 'U00...00"
240test_expect_success 'git submodule status should display the merge conflict properly with merge base' '
241 (cd merge-search &&
242 cat >.gitmodules <<EOF &&
243[submodule "sub"]
244 path = sub
245 url = $TRASH_DIRECTORY/sub
246EOF
247 cat >expect <<EOF &&
2197f879 248U$ZERO_OID sub
313ee0d6
NMC
249EOF
250 git submodule status > actual &&
251 test_cmp expect actual &&
252 git reset --hard)
253'
254
255# Check that the conflicting submodule is detected when it is
256# not in the common ancestor. status should be 'U00...00"
257test_expect_success 'git submodule status should display the merge conflict properly without merge-base' '
258 (cd merge-search &&
259 git checkout -b test-no-merge-base g &&
260 test_must_fail git merge b &&
261 cat >.gitmodules <<EOF &&
262[submodule "sub"]
263 path = sub
264 url = $TRASH_DIRECTORY/sub
265EOF
266 cat >expect <<EOF &&
2197f879 267U$ZERO_OID sub
313ee0d6
NMC
268EOF
269 git submodule status > actual &&
270 test_cmp expect actual &&
271 git reset --hard)
272'
273
274
0eb6574c 275test_expect_success 'merging with a modify/modify conflict between merge bases' '
f37ae35e
CB
276 git reset --hard HEAD &&
277 git checkout -b test2 c &&
278 git merge d
f37ae35e
CB
279'
280
72251b7d
BK
281# canonical criss-cross history in top and submodule
282test_expect_success 'setup for recursive merge with submodule' '
283 mkdir merge-recursive &&
284 (cd merge-recursive &&
285 git init &&
286 mkdir sub &&
287 (cd sub &&
288 git init &&
289 test_commit a &&
5902f5f4 290 git checkout -b sub-b main &&
72251b7d 291 test_commit b &&
5902f5f4 292 git checkout -b sub-c main &&
72251b7d
BK
293 test_commit c &&
294 git checkout -b sub-bc sub-b &&
295 git merge sub-c &&
296 git checkout -b sub-cb sub-c &&
297 git merge sub-b &&
5902f5f4 298 git checkout main) &&
72251b7d
BK
299 git add sub &&
300 git commit -m a &&
5902f5f4 301 git checkout -b top-b main &&
72251b7d
BK
302 (cd sub && git checkout sub-b) &&
303 git add sub &&
304 git commit -m b &&
5902f5f4 305 git checkout -b top-c main &&
72251b7d
BK
306 (cd sub && git checkout sub-c) &&
307 git add sub &&
308 git commit -m c &&
309 git checkout -b top-bc top-b &&
310 git merge -s ours --no-commit top-c &&
311 (cd sub && git checkout sub-bc) &&
312 git add sub &&
313 git commit -m bc &&
314 git checkout -b top-cb top-c &&
315 git merge -s ours --no-commit top-b &&
316 (cd sub && git checkout sub-cb) &&
317 git add sub &&
318 git commit -m cb)
319'
320
321# merge should leave submodule unmerged in index
80988783 322test_expect_success 'recursive merge with submodule' '
72251b7d
BK
323 (cd merge-recursive &&
324 test_must_fail git merge top-bc &&
325 echo "160000 $(git rev-parse top-cb:sub) 2 sub" > expect2 &&
326 echo "160000 $(git rev-parse top-bc:sub) 3 sub" > expect3 &&
327 git ls-files -u > actual &&
328 grep "$(cat expect2)" actual > /dev/null &&
329 grep "$(cat expect3)" actual > /dev/null)
330'
331
594a8673
EN
332# File/submodule conflict
333# Commit O: <empty>
334# Commit A: path (submodule)
335# Commit B: path
336# Expected: path/ is submodule and file contents for B's path are somewhere
337
338test_expect_success 'setup file/submodule conflict' '
6693fb3f 339 git init file-submodule &&
594a8673
EN
340 (
341 cd file-submodule &&
342
343 git commit --allow-empty -m O &&
344
345 git branch A &&
346 git branch B &&
347
348 git checkout B &&
349 echo content >path &&
350 git add path &&
351 git commit -m B &&
352
353 git checkout A &&
6693fb3f 354 git init path &&
594a8673
EN
355 test_commit -C path world &&
356 git submodule add ./path &&
357 git commit -m A
358 )
359'
360
aa2faac0 361test_expect_merge_algorithm failure success 'file/submodule conflict' '
594a8673
EN
362 test_when_finished "git -C file-submodule reset --hard" &&
363 (
364 cd file-submodule &&
365
366 git checkout A^0 &&
367 test_must_fail git merge B^0 &&
368
369 git ls-files -s >out &&
370 test_line_count = 3 out &&
371 git ls-files -u >out &&
372 test_line_count = 2 out &&
373
374 # path/ is still a submodule
375 test_path_is_dir path/.git &&
376
377 # There is a submodule at "path", so B:path cannot be written
378 # there. We expect it to be written somewhere in the same
379 # directory, though, so just grep for its content in all
380 # files, and ignore "grep: path: Is a directory" message
381 echo Checking if contents from B:path showed up anywhere &&
382 grep -q content * 2>/dev/null
383 )
384'
385
587421eb
EN
386test_expect_success 'file/submodule conflict; merge --abort works afterward' '
387 test_when_finished "git -C file-submodule reset --hard" &&
388 (
389 cd file-submodule &&
390
391 git checkout A^0 &&
392 test_must_fail git merge B^0 >out 2>err &&
393
394 test_path_is_file .git/MERGE_HEAD &&
395 git merge --abort
396 )
397'
398
e81c7d41
EN
399# Directory/submodule conflict
400# Commit O: <empty>
401# Commit A: path (submodule), with sole tracked file named 'world'
402# Commit B1: path/file
403# Commit B2: path/world
404#
405# Expected from merge of A & B1:
406# Contents under path/ from commit B1 are renamed elsewhere; we do not
407# want to write files from one of our tracked directories into a submodule
408#
409# Expected from merge of A & B2:
410# Similar to last merge, but with a slight twist: we don't want paths
411# under the submodule to be treated as untracked or in the way.
412
413test_expect_success 'setup directory/submodule conflict' '
6693fb3f 414 git init directory-submodule &&
e81c7d41
EN
415 (
416 cd directory-submodule &&
417
418 git commit --allow-empty -m O &&
419
420 git branch A &&
421 git branch B1 &&
422 git branch B2 &&
423
424 git checkout B1 &&
425 mkdir path &&
426 echo contents >path/file &&
427 git add path/file &&
428 git commit -m B1 &&
429
430 git checkout B2 &&
431 mkdir path &&
432 echo contents >path/world &&
433 git add path/world &&
434 git commit -m B2 &&
435
436 git checkout A &&
6693fb3f 437 git init path &&
e81c7d41
EN
438 test_commit -C path hello world &&
439 git submodule add ./path &&
440 git commit -m A
441 )
442'
443
444test_expect_failure 'directory/submodule conflict; keep submodule clean' '
445 test_when_finished "git -C directory-submodule reset --hard" &&
446 (
447 cd directory-submodule &&
448
449 git checkout A^0 &&
450 test_must_fail git merge B1^0 &&
451
452 git ls-files -s >out &&
453 test_line_count = 3 out &&
454 git ls-files -u >out &&
455 test_line_count = 1 out &&
456
457 # path/ is still a submodule
458 test_path_is_dir path/.git &&
459
460 echo Checking if contents from B1:path/file showed up &&
461 # Would rather use grep -r, but that is GNU extension...
462 git ls-files -co | xargs grep -q contents 2>/dev/null &&
463
464 # However, B1:path/file should NOT have shown up at path/file,
465 # because we should not write into the submodule
466 test_path_is_missing path/file
467 )
468'
469
aa2faac0 470test_expect_merge_algorithm failure success !FAIL_PREREQS 'directory/submodule conflict; should not treat submodule files as untracked or in the way' '
e81c7d41
EN
471 test_when_finished "git -C directory-submodule/path reset --hard" &&
472 test_when_finished "git -C directory-submodule reset --hard" &&
473 (
474 cd directory-submodule &&
475
476 git checkout A^0 &&
477 test_must_fail git merge B2^0 >out 2>err &&
478
479 # We do not want files within the submodule to prevent the
480 # merge from starting; we should not be writing to such paths
481 # anyway.
482 test_i18ngrep ! "refusing to lose untracked file at" err
587421eb
EN
483 )
484'
485
486test_expect_failure 'directory/submodule conflict; merge --abort works afterward' '
487 test_when_finished "git -C directory-submodule/path reset --hard" &&
488 test_when_finished "git -C directory-submodule reset --hard" &&
489 (
490 cd directory-submodule &&
e81c7d41 491
587421eb
EN
492 git checkout A^0 &&
493 test_must_fail git merge B2^0 &&
494 test_path_is_file .git/MERGE_HEAD &&
495
496 # merge --abort should succeed, should clear .git/MERGE_HEAD,
497 # and should not leave behind any conflicted files
498 git merge --abort &&
499 test_path_is_missing .git/MERGE_HEAD &&
500 git ls-files -u >conflicts &&
501 test_must_be_empty conflicts
e81c7d41
EN
502 )
503'
504
4057523a
CW
505# Setup:
506# - Submodule has 2 commits: a and b
507# - Superproject branch 'a' adds and commits submodule pointing to 'commit a'
508# - Superproject branch 'b' adds and commits submodule pointing to 'commit b'
509# If these two branches are now merged, there is no merge base
510test_expect_success 'setup for null merge base' '
511 mkdir no-merge-base &&
512 (cd no-merge-base &&
513 git init &&
514 mkdir sub &&
515 (cd sub &&
516 git init &&
517 echo "file-a" > file-a &&
518 git add file-a &&
519 git commit -m "commit a") &&
520 git commit --allow-empty -m init &&
521 git branch init &&
522 git checkout -b a init &&
523 git add sub &&
524 git commit -m "a" &&
525 git switch main &&
526 (cd sub &&
527 echo "file-b" > file-b &&
528 git add file-b &&
529 git commit -m "commit b"))
530'
531
532test_expect_success 'merging should fail with no merge base' '
533 (cd no-merge-base &&
534 git checkout -b b init &&
535 git add sub &&
536 git commit -m "b" &&
537 test_must_fail git merge a >actual &&
538 if test "$GIT_TEST_MERGE_ALGORITHM" = ort
539 then
540 sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short HEAD^1)" &&
541 grep "$sub_expect" actual
542 fi)
543'
544
f37ae35e 545test_done