3 test_description
='test push with submodules'
5 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
=main
6 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
8 GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB
=1
9 export GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB
11 TEST_PASSES_SANITIZE_LEAK
=true
14 test_expect_success setup
'
16 GIT_DIR=pub.git git init --bare &&
17 GIT_DIR=pub.git git config receive.fsckobjects true &&
22 git config push.default matching &&
27 git config push.default matching &&
30 git commit -m "Initial junk"
33 git commit -m "Initial superproject"
37 test_expect_success
'push works with recorded gitlink' '
40 git push ../pub.git main
44 test_expect_success
'push if submodule has no remote' '
49 git commit -m "Second junk"
54 git commit -m "Second commit for gar/bage" &&
55 git push --recurse-submodules=check ../pub.git main
59 test_expect_success
'push fails if submodule commit not on remote' '
62 git clone --bare bage ../../submodule.git &&
64 git remote add origin ../../../submodule.git &&
68 git commit -m "Third junk"
73 git commit -m "Third commit for gar/bage" &&
74 # the push should fail with --recurse-submodules=check
75 # on the command line...
76 test_must_fail git push --recurse-submodules=check ../pub.git main &&
78 # ...or if specified in the configuration..
79 test_must_fail git -c push.recurseSubmodules=check push ../pub.git main
83 test_expect_success
'push succeeds after commit was pushed to remote' '
90 git push --recurse-submodules=check ../pub.git main
94 test_expect_success
'push succeeds if submodule commit not on remote but using on-demand on command line' '
97 >recurse-on-demand-on-command-line &&
98 git add recurse-on-demand-on-command-line &&
99 git commit -m "Recurse on-demand on command line junk"
104 git commit -m "Recurse on-demand on command line for gar/bage" &&
105 git push --recurse-submodules=on-demand ../pub.git main &&
106 # Check that the supermodule commit got there
107 git fetch ../pub.git &&
108 git diff --quiet FETCH_HEAD main &&
109 # Check that the submodule commit got there too
111 git diff --quiet origin/main main
115 test_expect_success
'push succeeds if submodule commit not on remote but using on-demand from config' '
118 >recurse-on-demand-from-config &&
119 git add recurse-on-demand-from-config &&
120 git commit -m "Recurse on-demand from config junk"
125 git commit -m "Recurse on-demand from config for gar/bage" &&
126 git -c push.recurseSubmodules=on-demand push ../pub.git main &&
127 # Check that the supermodule commit got there
128 git fetch ../pub.git &&
129 git diff --quiet FETCH_HEAD main &&
130 # Check that the submodule commit got there too
132 git diff --quiet origin/main main
136 test_expect_success
'push succeeds if submodule commit not on remote but using auto-on-demand via submodule.recurse config' '
139 >recurse-on-demand-from-submodule-recurse-config &&
140 git add recurse-on-demand-from-submodule-recurse-config &&
141 git commit -m "Recurse submodule.recurse from config junk"
146 git commit -m "Recurse submodule.recurse from config for gar/bage" &&
147 git -c submodule.recurse push ../pub.git main &&
148 # Check that the supermodule commit got there
149 git fetch ../pub.git &&
150 git diff --quiet FETCH_HEAD main &&
151 # Check that the submodule commit got there too
153 git diff --quiet origin/main main
157 test_expect_success
'push recurse-submodules on command line overrides config' '
160 >recurse-check-on-command-line-overriding-config &&
161 git add recurse-check-on-command-line-overriding-config &&
162 git commit -m "Recurse on command-line overriding config junk"
167 git commit -m "Recurse on command-line overriding config for gar/bage" &&
169 # Ensure that we can override on-demand in the config
170 # to just check submodules
171 test_must_fail git -c push.recurseSubmodules=on-demand push --recurse-submodules=check ../pub.git main &&
172 # Check that the supermodule commit did not get there
173 git fetch ../pub.git &&
174 git diff --quiet FETCH_HEAD main^ &&
175 # Check that the submodule commit did not get there
176 (cd gar/bage && git diff --quiet origin/main main^) &&
178 # Ensure that we can override check in the config to
179 # disable submodule recursion entirely
180 (cd gar/bage && git diff --quiet origin/main main^) &&
181 git -c push.recurseSubmodules=on-demand push --recurse-submodules=no ../pub.git main &&
182 git fetch ../pub.git &&
183 git diff --quiet FETCH_HEAD main &&
184 (cd gar/bage && git diff --quiet origin/main main^) &&
186 # Ensure that we can override check in the config to
187 # disable submodule recursion entirely (alternative form)
188 git -c push.recurseSubmodules=on-demand push --no-recurse-submodules ../pub.git main &&
189 git fetch ../pub.git &&
190 git diff --quiet FETCH_HEAD main &&
191 (cd gar/bage && git diff --quiet origin/main main^) &&
193 # Ensure that we can override check in the config to
194 # push the submodule too
195 git -c push.recurseSubmodules=check push --recurse-submodules=on-demand ../pub.git main &&
196 git fetch ../pub.git &&
197 git diff --quiet FETCH_HEAD main &&
198 (cd gar/bage && git diff --quiet origin/main main)
202 test_expect_success
'push recurse-submodules last one wins on command line' '
205 >recurse-check-on-command-line-overriding-earlier-command-line &&
206 git add recurse-check-on-command-line-overriding-earlier-command-line &&
207 git commit -m "Recurse on command-line overriding earlier command-line junk"
212 git commit -m "Recurse on command-line overriding earlier command-line for gar/bage" &&
214 # should result in "check"
215 test_must_fail git push --recurse-submodules=on-demand --recurse-submodules=check ../pub.git main &&
216 # Check that the supermodule commit did not get there
217 git fetch ../pub.git &&
218 git diff --quiet FETCH_HEAD main^ &&
219 # Check that the submodule commit did not get there
220 (cd gar/bage && git diff --quiet origin/main main^) &&
222 # should result in "no"
223 git push --recurse-submodules=on-demand --recurse-submodules=no ../pub.git main &&
224 # Check that the supermodule commit did get there
225 git fetch ../pub.git &&
226 git diff --quiet FETCH_HEAD main &&
227 # Check that the submodule commit did not get there
228 (cd gar/bage && git diff --quiet origin/main main^) &&
230 # should result in "no"
231 git push --recurse-submodules=on-demand --no-recurse-submodules ../pub.git main &&
232 # Check that the submodule commit did not get there
233 (cd gar/bage && git diff --quiet origin/main main^) &&
235 # But the options in the other order should push the submodule
236 git push --recurse-submodules=check --recurse-submodules=on-demand ../pub.git main &&
237 # Check that the submodule commit did get there
238 git fetch ../pub.git &&
239 (cd gar/bage && git diff --quiet origin/main main)
243 test_expect_success
'push succeeds if submodule commit not on remote using on-demand from cmdline overriding config' '
246 >recurse-on-demand-on-command-line-overriding-config &&
247 git add recurse-on-demand-on-command-line-overriding-config &&
248 git commit -m "Recurse on-demand on command-line overriding config junk"
253 git commit -m "Recurse on-demand on command-line overriding config for gar/bage" &&
254 git -c push.recurseSubmodules=check push --recurse-submodules=on-demand ../pub.git main &&
255 # Check that the supermodule commit got there
256 git fetch ../pub.git &&
257 git diff --quiet FETCH_HEAD main &&
258 # Check that the submodule commit got there
260 git diff --quiet origin/main main
264 test_expect_success
'push succeeds if submodule commit disabling recursion from cmdline overriding config' '
267 >recurse-disable-on-command-line-overriding-config &&
268 git add recurse-disable-on-command-line-overriding-config &&
269 git commit -m "Recurse disable on command-line overriding config junk"
274 git commit -m "Recurse disable on command-line overriding config for gar/bage" &&
275 git -c push.recurseSubmodules=check push --recurse-submodules=no ../pub.git main &&
276 # Check that the supermodule commit got there
277 git fetch ../pub.git &&
278 git diff --quiet FETCH_HEAD main &&
279 # But that the submodule commit did not
280 ( cd gar/bage && git diff --quiet origin/main main^ ) &&
281 # Now push it to avoid confusing future tests
282 git push --recurse-submodules=on-demand ../pub.git main
286 test_expect_success
'push succeeds if submodule commit disabling recursion from cmdline (alternative form) overriding config' '
289 >recurse-disable-on-command-line-alt-overriding-config &&
290 git add recurse-disable-on-command-line-alt-overriding-config &&
291 git commit -m "Recurse disable on command-line alternative overriding config junk"
296 git commit -m "Recurse disable on command-line alternative overriding config for gar/bage" &&
297 git -c push.recurseSubmodules=check push --no-recurse-submodules ../pub.git main &&
298 # Check that the supermodule commit got there
299 git fetch ../pub.git &&
300 git diff --quiet FETCH_HEAD main &&
301 # But that the submodule commit did not
302 ( cd gar/bage && git diff --quiet origin/main main^ ) &&
303 # Now push it to avoid confusing future tests
304 git push --recurse-submodules=on-demand ../pub.git main
308 test_expect_success
'submodule entry pointing at a tag is error' '
309 git -C work/gar/bage tag -a test1 -m "tag" &&
310 tag=$(git -C work/gar/bage rev-parse test1^{tag}) &&
311 git -C work update-index --cacheinfo 160000 "$tag" gar/bage &&
312 git -C work commit -m "bad commit" &&
313 test_when_finished "git -C work reset --hard HEAD^" &&
314 test_must_fail git -C work push --recurse-submodules=on-demand ../pub.git main 2>err &&
315 test_grep "is a tag, not a commit" err
318 test_expect_success
'push fails if recurse submodules option passed as yes' '
321 >recurse-push-fails-if-recurse-submodules-passed-as-yes &&
322 git add recurse-push-fails-if-recurse-submodules-passed-as-yes &&
323 git commit -m "Recurse push fails if recurse submodules option passed as yes"
328 git commit -m "Recurse push fails if recurse submodules option passed as yes for gar/bage" &&
329 test_must_fail git push --recurse-submodules=yes ../pub.git main &&
330 test_must_fail git -c push.recurseSubmodules=yes push ../pub.git main &&
331 git push --recurse-submodules=on-demand ../pub.git main
335 test_expect_success
'push fails when commit on multiple branches if one branch has no remote' '
340 git commit -m "Fourth junk"
344 git branch branch2 &&
346 git commit -m "Fourth commit for gar/bage" &&
347 git checkout branch2 &&
354 git commit -m "First junk" &&
355 test_must_fail git push --recurse-submodules=check ../pub.git
359 test_expect_success
'push succeeds if submodule has no remote and is on the first superproject commit' '
369 git commit -m "initial"
372 git commit -m "added submodule" &&
373 git push --recurse-submodules=check origin main
377 test_expect_success
'push unpushed submodules when not needed' '
385 git commit -m "Fifth junk" &&
387 git rev-parse origin/main >../../../expected
391 git commit -m "Fifth commit for gar/bage" &&
392 git push --recurse-submodules=on-demand ../pub.git main
396 git rev-parse main >../actual
398 test_cmp expected actual
401 test_expect_success
'push unpushed submodules when not needed 2' '
404 git rev-parse main >../expected
412 git commit -m "Sixth junk"
416 git commit -m "Second junk for work" &&
417 git push --recurse-submodules=on-demand ../pub.git main
421 git rev-parse main >../actual
423 test_cmp expected actual
426 test_expect_success
'push unpushed submodules recursively' '
434 git commit -m "Seventh junk" &&
435 git rev-parse main >../../../expected
439 git commit -m "Seventh commit for gar/bage" &&
440 git push --recurse-submodules=on-demand ../pub.git main
444 git rev-parse main >../actual
446 test_cmp expected actual
449 test_expect_success
'push unpushable submodule recursively fails' '
454 git rev-parse origin/main >../../../expected &&
455 git checkout main~0 &&
458 git commit -m "Eighth junk"
461 git commit -m "Eighth commit for gar/bage" &&
462 test_must_fail git push --recurse-submodules=on-demand ../pub.git main
466 git rev-parse main >../actual
468 test_when_finished git -C work reset --hard main^ &&
469 test_cmp expected actual
472 test_expect_success
'push --dry-run does not recursively update submodules' '
476 git rev-parse main >../../../expected_submodule &&
479 git commit -m "Ninth junk" &&
481 # Go up to 'work
' directory
484 git rev-parse main >../expected_pub &&
486 git commit -m "Ninth commit for gar/bage" &&
487 git push --dry-run --recurse-submodules=on-demand ../pub.git main
489 git -C submodule.git rev-parse main >actual_submodule &&
490 git -C pub.git rev-parse main >actual_pub &&
491 test_cmp expected_pub actual_pub &&
492 test_cmp expected_submodule actual_submodule
495 test_expect_success
'push --dry-run does not recursively update submodules' '
496 git -C work push --dry-run --recurse-submodules=only ../pub.git main &&
498 git -C submodule.git rev-parse main >actual_submodule &&
499 git -C pub.git rev-parse main >actual_pub &&
500 test_cmp expected_pub actual_pub &&
501 test_cmp expected_submodule actual_submodule
504 test_expect_success
'push only unpushed submodules recursively' '
505 git -C work/gar/bage rev-parse main >expected_submodule &&
506 git -C pub.git rev-parse main >expected_pub &&
508 git -C work push --recurse-submodules=only ../pub.git main &&
510 git -C submodule.git rev-parse main >actual_submodule &&
511 git -C pub.git rev-parse main >actual_pub &&
512 test_cmp expected_submodule actual_submodule &&
513 test_cmp expected_pub actual_pub
518 git init upstream
/sub
&&
519 git init upstream
/sub
/deepsub
&&
520 test_commit
-C upstream
/sub
/deepsub innermost
&&
521 git
-C upstream
/sub submodule add .
/deepsub deepsub
&&
522 git
-C upstream
/sub commit
-m middle
&&
523 git
-C upstream submodule add .
/sub sub
&&
524 git
-C upstream commit
-m outermost
&&
526 git
-c protocol.
file.allow
=always clone
--recurse-submodules upstream downstream
&&
527 git
-C downstream
/sub
/deepsub checkout
-b downstream-branch
&&
528 git
-C downstream
/sub checkout
-b downstream-branch
&&
529 git
-C downstream checkout
-b downstream-branch
532 new_downstream_commits
() {
533 test_commit
-C downstream
/sub
/deepsub new-innermost
&&
534 git
-C downstream
/sub add deepsub
&&
535 git
-C downstream
/sub commit
-m new-middle
&&
536 git
-C downstream add sub
&&
537 git
-C downstream commit
-m new-outermost
540 test_expect_success
'push with push.recurseSubmodules=only on superproject' '
541 test_when_finished rm -rf upstream downstream &&
543 new_downstream_commits &&
544 git -C downstream config push.recurseSubmodules only &&
545 git -C downstream push origin downstream-branch &&
547 test_must_fail git -C upstream rev-parse refs/heads/downstream-branch &&
548 git -C upstream/sub rev-parse refs/heads/downstream-branch &&
549 test_must_fail git -C upstream/sub/deepsub rev-parse refs/heads/downstream-branch
552 test_expect_success
'push with push.recurseSubmodules=only on superproject and top-level submodule' '
553 test_when_finished rm -rf upstream downstream &&
555 new_downstream_commits &&
556 git -C downstream config push.recurseSubmodules only &&
557 git -C downstream/sub config push.recurseSubmodules only &&
558 git -C downstream push origin downstream-branch 2> err &&
560 test_must_fail git -C upstream rev-parse refs/heads/downstream-branch &&
561 git -C upstream/sub rev-parse refs/heads/downstream-branch &&
562 git -C upstream/sub/deepsub rev-parse refs/heads/downstream-branch &&
563 grep "recursing into submodule with push.recurseSubmodules=only; using on-demand instead" err
566 test_expect_success
'push propagating the remotes name to a submodule' '
567 git -C work remote add origin ../pub.git &&
568 git -C work remote add pub ../pub.git &&
570 > work/gar/bage/junk10 &&
571 git -C work/gar/bage add junk10 &&
572 git -C work/gar/bage commit -m "Tenth junk" &&
573 git -C work add gar/bage &&
574 git -C work commit -m "Tenth junk added to gar/bage" &&
576 # Fails when submodule does not have a matching remote
577 test_must_fail git -C work push --recurse-submodules=on-demand pub main &&
578 # Succeeds when submodules has matching remote and refspec
579 git -C work push --recurse-submodules=on-demand origin main &&
581 git -C submodule.git rev-parse main >actual_submodule &&
582 git -C pub.git rev-parse main >actual_pub &&
583 git -C work/gar/bage rev-parse main >expected_submodule &&
584 git -C work rev-parse main >expected_pub &&
585 test_cmp expected_submodule actual_submodule &&
586 test_cmp expected_pub actual_pub
589 test_expect_success
'push propagating refspec to a submodule' '
590 > work/gar/bage/junk11 &&
591 git -C work/gar/bage add junk11 &&
592 git -C work/gar/bage commit -m "Eleventh junk" &&
594 git -C work checkout branch2 &&
595 git -C work add gar/bage &&
596 git -C work commit -m "updating gar/bage in branch2" &&
598 # Fails when submodule does not have a matching branch
599 test_must_fail git -C work push --recurse-submodules=on-demand origin branch2 &&
600 # Fails when refspec includes an object id
601 test_must_fail git -C work push --recurse-submodules=on-demand origin \
602 "$(git -C work rev-parse branch2):refs/heads/branch2" &&
603 # Fails when refspec includes HEAD and parent and submodule do not
604 # have the same named branch checked out
605 test_must_fail git -C work push --recurse-submodules=on-demand origin \
606 HEAD:refs/heads/branch2 &&
608 git -C work/gar/bage branch branch2 main &&
609 git -C work push --recurse-submodules=on-demand origin branch2 &&
611 git -C submodule.git rev-parse branch2 >actual_submodule &&
612 git -C pub.git rev-parse branch2 >actual_pub &&
613 git -C work/gar/bage rev-parse branch2 >expected_submodule &&
614 git -C work rev-parse branch2 >expected_pub &&
615 test_cmp expected_submodule actual_submodule &&
616 test_cmp expected_pub actual_pub
619 test_expect_success
'push propagating HEAD refspec to a submodule' '
620 git -C work/gar/bage checkout branch2 &&
621 > work/gar/bage/junk12 &&
622 git -C work/gar/bage add junk12 &&
623 git -C work/gar/bage commit -m "Twelfth junk" &&
625 git -C work checkout branch2 &&
626 git -C work add gar/bage &&
627 git -C work commit -m "updating gar/bage in branch2" &&
629 # Passes since the superproject and submodules HEAD are both on branch2
630 git -C work push --recurse-submodules=on-demand origin \
631 HEAD:refs/heads/branch2 &&
633 git -C submodule.git rev-parse branch2 >actual_submodule &&
634 git -C pub.git rev-parse branch2 >actual_pub &&
635 git -C work/gar/bage rev-parse branch2 >expected_submodule &&
636 git -C work rev-parse branch2 >expected_pub &&
637 test_cmp expected_submodule actual_submodule &&
638 test_cmp expected_pub actual_pub