]> git.ipfire.org Git - thirdparty/git.git/blob - t/t5516-fetch-push.sh
Merge branch 'ab/reflog-prep'
[thirdparty/git.git] / t / t5516-fetch-push.sh
1 #!/bin/sh
2
3 test_description='Basic fetch/push functionality.
4
5 This test checks the following functionality:
6
7 * command-line syntax
8 * refspecs
9 * fast-forward detection, and overriding it
10 * configuration
11 * hooks
12 * --porcelain output format
13 * hiderefs
14 * reflogs
15 '
16
17 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
18 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
19
20 . ./test-lib.sh
21
22 D=$(pwd)
23
24 mk_empty () {
25 repo_name="$1"
26 rm -fr "$repo_name" &&
27 mkdir "$repo_name" &&
28 (
29 cd "$repo_name" &&
30 git init &&
31 git config receive.denyCurrentBranch warn &&
32 mv .git/hooks .git/hooks-disabled
33 )
34 }
35
36 mk_test () {
37 repo_name="$1"
38 shift
39
40 mk_empty "$repo_name" &&
41 (
42 for ref in "$@"
43 do
44 git push "$repo_name" $the_first_commit:refs/$ref ||
45 exit
46 done &&
47 cd "$repo_name" &&
48 for ref in "$@"
49 do
50 echo "$the_first_commit" >expect &&
51 git show-ref -s --verify refs/$ref >actual &&
52 test_cmp expect actual ||
53 exit
54 done &&
55 git fsck --full
56 )
57 }
58
59 mk_test_with_hooks() {
60 repo_name=$1
61 mk_test "$@" &&
62 (
63 cd "$repo_name" &&
64 mkdir .git/hooks &&
65 cd .git/hooks &&
66
67 cat >pre-receive <<-'EOF' &&
68 #!/bin/sh
69 cat - >>pre-receive.actual
70 EOF
71
72 cat >update <<-'EOF' &&
73 #!/bin/sh
74 printf "%s %s %s\n" "$@" >>update.actual
75 EOF
76
77 cat >post-receive <<-'EOF' &&
78 #!/bin/sh
79 cat - >>post-receive.actual
80 EOF
81
82 cat >post-update <<-'EOF' &&
83 #!/bin/sh
84 for ref in "$@"
85 do
86 printf "%s\n" "$ref" >>post-update.actual
87 done
88 EOF
89
90 chmod +x pre-receive update post-receive post-update
91 )
92 }
93
94 mk_child() {
95 rm -rf "$2" &&
96 git clone "$1" "$2"
97 }
98
99 check_push_result () {
100 test $# -ge 3 ||
101 BUG "check_push_result requires at least 3 parameters"
102
103 repo_name="$1"
104 shift
105
106 (
107 cd "$repo_name" &&
108 echo "$1" >expect &&
109 shift &&
110 for ref in "$@"
111 do
112 git show-ref -s --verify refs/$ref >actual &&
113 test_cmp expect actual ||
114 exit
115 done &&
116 git fsck --full
117 )
118 }
119
120 test_expect_success setup '
121
122 >path1 &&
123 git add path1 &&
124 test_tick &&
125 git commit -a -m repo &&
126 the_first_commit=$(git show-ref -s --verify refs/heads/main) &&
127
128 >path2 &&
129 git add path2 &&
130 test_tick &&
131 git commit -a -m second &&
132 the_commit=$(git show-ref -s --verify refs/heads/main)
133
134 '
135
136 test_expect_success 'fetch without wildcard' '
137 mk_empty testrepo &&
138 (
139 cd testrepo &&
140 git fetch .. refs/heads/main:refs/remotes/origin/main &&
141
142 echo "$the_commit commit refs/remotes/origin/main" >expect &&
143 git for-each-ref refs/remotes/origin >actual &&
144 test_cmp expect actual
145 )
146 '
147
148 test_expect_success 'fetch with wildcard' '
149 mk_empty testrepo &&
150 (
151 cd testrepo &&
152 git config remote.up.url .. &&
153 git config remote.up.fetch "refs/heads/*:refs/remotes/origin/*" &&
154 git fetch up &&
155
156 echo "$the_commit commit refs/remotes/origin/main" >expect &&
157 git for-each-ref refs/remotes/origin >actual &&
158 test_cmp expect actual
159 )
160 '
161
162 test_expect_success 'fetch with insteadOf' '
163 mk_empty testrepo &&
164 (
165 TRASH=$(pwd)/ &&
166 cd testrepo &&
167 git config "url.$TRASH.insteadOf" trash/ &&
168 git config remote.up.url trash/. &&
169 git config remote.up.fetch "refs/heads/*:refs/remotes/origin/*" &&
170 git fetch up &&
171
172 echo "$the_commit commit refs/remotes/origin/main" >expect &&
173 git for-each-ref refs/remotes/origin >actual &&
174 test_cmp expect actual
175 )
176 '
177
178 test_expect_success 'fetch with pushInsteadOf (should not rewrite)' '
179 mk_empty testrepo &&
180 (
181 TRASH=$(pwd)/ &&
182 cd testrepo &&
183 git config "url.trash/.pushInsteadOf" "$TRASH" &&
184 git config remote.up.url "$TRASH." &&
185 git config remote.up.fetch "refs/heads/*:refs/remotes/origin/*" &&
186 git fetch up &&
187
188 echo "$the_commit commit refs/remotes/origin/main" >expect &&
189 git for-each-ref refs/remotes/origin >actual &&
190 test_cmp expect actual
191 )
192 '
193
194 grep_wrote () {
195 object_count=$1
196 file_name=$2
197 grep 'write_pack_file/wrote.*"value":"'$1'"' $2
198 }
199
200 test_expect_success 'push with negotiation' '
201 # Without negotiation
202 mk_empty testrepo &&
203 git push testrepo $the_first_commit:refs/remotes/origin/first_commit &&
204 test_commit -C testrepo unrelated_commit &&
205 git -C testrepo config receive.hideRefs refs/remotes/origin/first_commit &&
206 echo now pushing without negotiation &&
207 GIT_TRACE2_EVENT="$(pwd)/event" git -c protocol.version=2 push testrepo refs/heads/main:refs/remotes/origin/main &&
208 grep_wrote 5 event && # 2 commits, 2 trees, 1 blob
209
210 # Same commands, but with negotiation
211 rm event &&
212 mk_empty testrepo &&
213 git push testrepo $the_first_commit:refs/remotes/origin/first_commit &&
214 test_commit -C testrepo unrelated_commit &&
215 git -C testrepo config receive.hideRefs refs/remotes/origin/first_commit &&
216 GIT_TRACE2_EVENT="$(pwd)/event" git -c protocol.version=2 -c push.negotiate=1 push testrepo refs/heads/main:refs/remotes/origin/main &&
217 grep_wrote 2 event # 1 commit, 1 tree
218 '
219
220 test_expect_success 'push with negotiation proceeds anyway even if negotiation fails' '
221 rm event &&
222 mk_empty testrepo &&
223 git push testrepo $the_first_commit:refs/remotes/origin/first_commit &&
224 test_commit -C testrepo unrelated_commit &&
225 git -C testrepo config receive.hideRefs refs/remotes/origin/first_commit &&
226 GIT_TEST_PROTOCOL_VERSION=0 GIT_TRACE2_EVENT="$(pwd)/event" \
227 git -c push.negotiate=1 push testrepo refs/heads/main:refs/remotes/origin/main 2>err &&
228 grep_wrote 5 event && # 2 commits, 2 trees, 1 blob
229 test_i18ngrep "push negotiation failed" err
230 '
231
232 test_expect_success 'push without wildcard' '
233 mk_empty testrepo &&
234
235 git push testrepo refs/heads/main:refs/remotes/origin/main &&
236 (
237 cd testrepo &&
238 echo "$the_commit commit refs/remotes/origin/main" >expect &&
239 git for-each-ref refs/remotes/origin >actual &&
240 test_cmp expect actual
241 )
242 '
243
244 test_expect_success 'push with wildcard' '
245 mk_empty testrepo &&
246
247 git push testrepo "refs/heads/*:refs/remotes/origin/*" &&
248 (
249 cd testrepo &&
250 echo "$the_commit commit refs/remotes/origin/main" >expect &&
251 git for-each-ref refs/remotes/origin >actual &&
252 test_cmp expect actual
253 )
254 '
255
256 test_expect_success 'push with insteadOf' '
257 mk_empty testrepo &&
258 TRASH="$(pwd)/" &&
259 test_config "url.$TRASH.insteadOf" trash/ &&
260 git push trash/testrepo refs/heads/main:refs/remotes/origin/main &&
261 (
262 cd testrepo &&
263 echo "$the_commit commit refs/remotes/origin/main" >expect &&
264 git for-each-ref refs/remotes/origin >actual &&
265 test_cmp expect actual
266 )
267 '
268
269 test_expect_success 'push with pushInsteadOf' '
270 mk_empty testrepo &&
271 TRASH="$(pwd)/" &&
272 test_config "url.$TRASH.pushInsteadOf" trash/ &&
273 git push trash/testrepo refs/heads/main:refs/remotes/origin/main &&
274 (
275 cd testrepo &&
276 echo "$the_commit commit refs/remotes/origin/main" >expect &&
277 git for-each-ref refs/remotes/origin >actual &&
278 test_cmp expect actual
279 )
280 '
281
282 test_expect_success 'push with pushInsteadOf and explicit pushurl (pushInsteadOf should not rewrite)' '
283 mk_empty testrepo &&
284 test_config "url.trash2/.pushInsteadOf" testrepo/ &&
285 test_config "url.trash3/.pushInsteadOf" trash/wrong &&
286 test_config remote.r.url trash/wrong &&
287 test_config remote.r.pushurl "testrepo/" &&
288 git push r refs/heads/main:refs/remotes/origin/main &&
289 (
290 cd testrepo &&
291 echo "$the_commit commit refs/remotes/origin/main" >expect &&
292 git for-each-ref refs/remotes/origin >actual &&
293 test_cmp expect actual
294 )
295 '
296
297 test_expect_success 'push with matching heads' '
298
299 mk_test testrepo heads/main &&
300 git push testrepo : &&
301 check_push_result testrepo $the_commit heads/main
302
303 '
304
305 test_expect_success 'push with matching heads on the command line' '
306
307 mk_test testrepo heads/main &&
308 git push testrepo : &&
309 check_push_result testrepo $the_commit heads/main
310
311 '
312
313 test_expect_success 'failed (non-fast-forward) push with matching heads' '
314
315 mk_test testrepo heads/main &&
316 git push testrepo : &&
317 git commit --amend -massaged &&
318 test_must_fail git push testrepo &&
319 check_push_result testrepo $the_commit heads/main &&
320 git reset --hard $the_commit
321
322 '
323
324 test_expect_success 'push --force with matching heads' '
325
326 mk_test testrepo heads/main &&
327 git push testrepo : &&
328 git commit --amend -massaged &&
329 git push --force testrepo : &&
330 ! check_push_result testrepo $the_commit heads/main &&
331 git reset --hard $the_commit
332
333 '
334
335 test_expect_success 'push with matching heads and forced update' '
336
337 mk_test testrepo heads/main &&
338 git push testrepo : &&
339 git commit --amend -massaged &&
340 git push testrepo +: &&
341 ! check_push_result testrepo $the_commit heads/main &&
342 git reset --hard $the_commit
343
344 '
345
346 test_expect_success 'push with no ambiguity (1)' '
347
348 mk_test testrepo heads/main &&
349 git push testrepo main:main &&
350 check_push_result testrepo $the_commit heads/main
351
352 '
353
354 test_expect_success 'push with no ambiguity (2)' '
355
356 mk_test testrepo remotes/origin/main &&
357 git push testrepo main:origin/main &&
358 check_push_result testrepo $the_commit remotes/origin/main
359
360 '
361
362 test_expect_success 'push with colon-less refspec, no ambiguity' '
363
364 mk_test testrepo heads/main heads/t/main &&
365 git branch -f t/main main &&
366 git push testrepo main &&
367 check_push_result testrepo $the_commit heads/main &&
368 check_push_result testrepo $the_first_commit heads/t/main
369
370 '
371
372 test_expect_success 'push with weak ambiguity (1)' '
373
374 mk_test testrepo heads/main remotes/origin/main &&
375 git push testrepo main:main &&
376 check_push_result testrepo $the_commit heads/main &&
377 check_push_result testrepo $the_first_commit remotes/origin/main
378
379 '
380
381 test_expect_success 'push with weak ambiguity (2)' '
382
383 mk_test testrepo heads/main remotes/origin/main remotes/another/main &&
384 git push testrepo main:main &&
385 check_push_result testrepo $the_commit heads/main &&
386 check_push_result testrepo $the_first_commit remotes/origin/main remotes/another/main
387
388 '
389
390 test_expect_success 'push with ambiguity' '
391
392 mk_test testrepo heads/frotz tags/frotz &&
393 test_must_fail git push testrepo main:frotz &&
394 check_push_result testrepo $the_first_commit heads/frotz tags/frotz
395
396 '
397
398 test_expect_success 'push with colon-less refspec (1)' '
399
400 mk_test testrepo heads/frotz tags/frotz &&
401 git branch -f frotz main &&
402 git push testrepo frotz &&
403 check_push_result testrepo $the_commit heads/frotz &&
404 check_push_result testrepo $the_first_commit tags/frotz
405
406 '
407
408 test_expect_success 'push with colon-less refspec (2)' '
409
410 mk_test testrepo heads/frotz tags/frotz &&
411 if git show-ref --verify -q refs/heads/frotz
412 then
413 git branch -D frotz
414 fi &&
415 git tag -f frotz &&
416 git push -f testrepo frotz &&
417 check_push_result testrepo $the_commit tags/frotz &&
418 check_push_result testrepo $the_first_commit heads/frotz
419
420 '
421
422 test_expect_success 'push with colon-less refspec (3)' '
423
424 mk_test testrepo &&
425 if git show-ref --verify -q refs/tags/frotz
426 then
427 git tag -d frotz
428 fi &&
429 git branch -f frotz main &&
430 git push testrepo frotz &&
431 check_push_result testrepo $the_commit heads/frotz &&
432 test 1 = $( cd testrepo && git show-ref | wc -l )
433 '
434
435 test_expect_success 'push with colon-less refspec (4)' '
436
437 mk_test testrepo &&
438 if git show-ref --verify -q refs/heads/frotz
439 then
440 git branch -D frotz
441 fi &&
442 git tag -f frotz &&
443 git push testrepo frotz &&
444 check_push_result testrepo $the_commit tags/frotz &&
445 test 1 = $( cd testrepo && git show-ref | wc -l )
446
447 '
448
449 test_expect_success 'push head with non-existent, incomplete dest' '
450
451 mk_test testrepo &&
452 git push testrepo main:branch &&
453 check_push_result testrepo $the_commit heads/branch
454
455 '
456
457 test_expect_success 'push tag with non-existent, incomplete dest' '
458
459 mk_test testrepo &&
460 git tag -f v1.0 &&
461 git push testrepo v1.0:tag &&
462 check_push_result testrepo $the_commit tags/tag
463
464 '
465
466 test_expect_success 'push sha1 with non-existent, incomplete dest' '
467
468 mk_test testrepo &&
469 test_must_fail git push testrepo $(git rev-parse main):foo
470
471 '
472
473 test_expect_success 'push ref expression with non-existent, incomplete dest' '
474
475 mk_test testrepo &&
476 test_must_fail git push testrepo main^:branch
477
478 '
479
480 for head in HEAD @
481 do
482
483 test_expect_success "push with $head" '
484 mk_test testrepo heads/main &&
485 git checkout main &&
486 git push testrepo $head &&
487 check_push_result testrepo $the_commit heads/main
488 '
489
490 test_expect_success "push with $head nonexisting at remote" '
491 mk_test testrepo heads/main &&
492 git checkout -b local main &&
493 test_when_finished "git checkout main; git branch -D local" &&
494 git push testrepo $head &&
495 check_push_result testrepo $the_commit heads/local
496 '
497
498 test_expect_success "push with +$head" '
499 mk_test testrepo heads/main &&
500 git checkout -b local main &&
501 test_when_finished "git checkout main; git branch -D local" &&
502 git push testrepo main local &&
503 check_push_result testrepo $the_commit heads/main &&
504 check_push_result testrepo $the_commit heads/local &&
505
506 # Without force rewinding should fail
507 git reset --hard $head^ &&
508 test_must_fail git push testrepo $head &&
509 check_push_result testrepo $the_commit heads/local &&
510
511 # With force rewinding should succeed
512 git push testrepo +$head &&
513 check_push_result testrepo $the_first_commit heads/local
514 '
515
516 test_expect_success "push $head with non-existent, incomplete dest" '
517 mk_test testrepo &&
518 git checkout main &&
519 git push testrepo $head:branch &&
520 check_push_result testrepo $the_commit heads/branch
521
522 '
523
524 test_expect_success "push with config remote.*.push = $head" '
525 mk_test testrepo heads/local &&
526 git checkout main &&
527 git branch -f local $the_commit &&
528 test_when_finished "git branch -D local" &&
529 (
530 cd testrepo &&
531 git checkout local &&
532 git reset --hard $the_first_commit
533 ) &&
534 test_config remote.there.url testrepo &&
535 test_config remote.there.push $head &&
536 test_config branch.main.remote there &&
537 git push &&
538 check_push_result testrepo $the_commit heads/main &&
539 check_push_result testrepo $the_first_commit heads/local
540 '
541
542 done
543
544 test_expect_success "push to remote with no explicit refspec and config remote.*.push = src:dest" '
545 mk_test testrepo heads/main &&
546 git checkout $the_first_commit &&
547 test_config remote.there.url testrepo &&
548 test_config remote.there.push refs/heads/main:refs/heads/main &&
549 git push there &&
550 check_push_result testrepo $the_commit heads/main
551 '
552
553 test_expect_success 'push with remote.pushdefault' '
554 mk_test up_repo heads/main &&
555 mk_test down_repo heads/main &&
556 test_config remote.up.url up_repo &&
557 test_config remote.down.url down_repo &&
558 test_config branch.main.remote up &&
559 test_config remote.pushdefault down &&
560 test_config push.default matching &&
561 git push &&
562 check_push_result up_repo $the_first_commit heads/main &&
563 check_push_result down_repo $the_commit heads/main
564 '
565
566 test_expect_success 'push with config remote.*.pushurl' '
567
568 mk_test testrepo heads/main &&
569 git checkout main &&
570 test_config remote.there.url test2repo &&
571 test_config remote.there.pushurl testrepo &&
572 git push there : &&
573 check_push_result testrepo $the_commit heads/main
574 '
575
576 test_expect_success 'push with config branch.*.pushremote' '
577 mk_test up_repo heads/main &&
578 mk_test side_repo heads/main &&
579 mk_test down_repo heads/main &&
580 test_config remote.up.url up_repo &&
581 test_config remote.pushdefault side_repo &&
582 test_config remote.down.url down_repo &&
583 test_config branch.main.remote up &&
584 test_config branch.main.pushremote down &&
585 test_config push.default matching &&
586 git push &&
587 check_push_result up_repo $the_first_commit heads/main &&
588 check_push_result side_repo $the_first_commit heads/main &&
589 check_push_result down_repo $the_commit heads/main
590 '
591
592 test_expect_success 'branch.*.pushremote config order is irrelevant' '
593 mk_test one_repo heads/main &&
594 mk_test two_repo heads/main &&
595 test_config remote.one.url one_repo &&
596 test_config remote.two.url two_repo &&
597 test_config branch.main.pushremote two_repo &&
598 test_config remote.pushdefault one_repo &&
599 test_config push.default matching &&
600 git push &&
601 check_push_result one_repo $the_first_commit heads/main &&
602 check_push_result two_repo $the_commit heads/main
603 '
604
605 test_expect_success 'push with dry-run' '
606
607 mk_test testrepo heads/main &&
608 old_commit=$(git -C testrepo show-ref -s --verify refs/heads/main) &&
609 git push --dry-run testrepo : &&
610 check_push_result testrepo $old_commit heads/main
611 '
612
613 test_expect_success 'push updates local refs' '
614
615 mk_test testrepo heads/main &&
616 mk_child testrepo child &&
617 (
618 cd child &&
619 git pull .. main &&
620 git push &&
621 test $(git rev-parse main) = \
622 $(git rev-parse remotes/origin/main)
623 )
624
625 '
626
627 test_expect_success 'push updates up-to-date local refs' '
628
629 mk_test testrepo heads/main &&
630 mk_child testrepo child1 &&
631 mk_child testrepo child2 &&
632 (cd child1 && git pull .. main && git push) &&
633 (
634 cd child2 &&
635 git pull ../child1 main &&
636 git push &&
637 test $(git rev-parse main) = \
638 $(git rev-parse remotes/origin/main)
639 )
640
641 '
642
643 test_expect_success 'push preserves up-to-date packed refs' '
644
645 mk_test testrepo heads/main &&
646 mk_child testrepo child &&
647 (
648 cd child &&
649 git push &&
650 ! test -f .git/refs/remotes/origin/main
651 )
652
653 '
654
655 test_expect_success 'push does not update local refs on failure' '
656
657 mk_test testrepo heads/main &&
658 mk_child testrepo child &&
659 mkdir testrepo/.git/hooks &&
660 echo "#!/no/frobnication/today" >testrepo/.git/hooks/pre-receive &&
661 chmod +x testrepo/.git/hooks/pre-receive &&
662 (
663 cd child &&
664 git pull .. main &&
665 test_must_fail git push &&
666 test $(git rev-parse main) != \
667 $(git rev-parse remotes/origin/main)
668 )
669
670 '
671
672 test_expect_success 'allow deleting an invalid remote ref' '
673
674 mk_test testrepo heads/branch &&
675 rm -f testrepo/.git/objects/??/* &&
676 git push testrepo :refs/heads/branch &&
677 (cd testrepo && test_must_fail git rev-parse --verify refs/heads/branch)
678
679 '
680
681 test_expect_success 'pushing valid refs triggers post-receive and post-update hooks' '
682 mk_test_with_hooks testrepo heads/main heads/next &&
683 orgmain=$(cd testrepo && git show-ref -s --verify refs/heads/main) &&
684 newmain=$(git show-ref -s --verify refs/heads/main) &&
685 orgnext=$(cd testrepo && git show-ref -s --verify refs/heads/next) &&
686 newnext=$ZERO_OID &&
687 git push testrepo refs/heads/main:refs/heads/main :refs/heads/next &&
688 (
689 cd testrepo/.git &&
690 cat >pre-receive.expect <<-EOF &&
691 $orgmain $newmain refs/heads/main
692 $orgnext $newnext refs/heads/next
693 EOF
694
695 cat >update.expect <<-EOF &&
696 refs/heads/main $orgmain $newmain
697 refs/heads/next $orgnext $newnext
698 EOF
699
700 cat >post-receive.expect <<-EOF &&
701 $orgmain $newmain refs/heads/main
702 $orgnext $newnext refs/heads/next
703 EOF
704
705 cat >post-update.expect <<-EOF &&
706 refs/heads/main
707 refs/heads/next
708 EOF
709
710 test_cmp pre-receive.expect pre-receive.actual &&
711 test_cmp update.expect update.actual &&
712 test_cmp post-receive.expect post-receive.actual &&
713 test_cmp post-update.expect post-update.actual
714 )
715 '
716
717 test_expect_success 'deleting dangling ref triggers hooks with correct args' '
718 mk_test_with_hooks testrepo heads/branch &&
719 orig=$(git -C testrepo rev-parse refs/heads/branch) &&
720 rm -f testrepo/.git/objects/??/* &&
721 git push testrepo :refs/heads/branch &&
722 (
723 cd testrepo/.git &&
724 cat >pre-receive.expect <<-EOF &&
725 $orig $ZERO_OID refs/heads/branch
726 EOF
727
728 cat >update.expect <<-EOF &&
729 refs/heads/branch $orig $ZERO_OID
730 EOF
731
732 cat >post-receive.expect <<-EOF &&
733 $orig $ZERO_OID refs/heads/branch
734 EOF
735
736 cat >post-update.expect <<-EOF &&
737 refs/heads/branch
738 EOF
739
740 test_cmp pre-receive.expect pre-receive.actual &&
741 test_cmp update.expect update.actual &&
742 test_cmp post-receive.expect post-receive.actual &&
743 test_cmp post-update.expect post-update.actual
744 )
745 '
746
747 test_expect_success 'deletion of a non-existent ref is not fed to post-receive and post-update hooks' '
748 mk_test_with_hooks testrepo heads/main &&
749 orgmain=$(cd testrepo && git show-ref -s --verify refs/heads/main) &&
750 newmain=$(git show-ref -s --verify refs/heads/main) &&
751 git push testrepo main :refs/heads/nonexistent &&
752 (
753 cd testrepo/.git &&
754 cat >pre-receive.expect <<-EOF &&
755 $orgmain $newmain refs/heads/main
756 $ZERO_OID $ZERO_OID refs/heads/nonexistent
757 EOF
758
759 cat >update.expect <<-EOF &&
760 refs/heads/main $orgmain $newmain
761 refs/heads/nonexistent $ZERO_OID $ZERO_OID
762 EOF
763
764 cat >post-receive.expect <<-EOF &&
765 $orgmain $newmain refs/heads/main
766 EOF
767
768 cat >post-update.expect <<-EOF &&
769 refs/heads/main
770 EOF
771
772 test_cmp pre-receive.expect pre-receive.actual &&
773 test_cmp update.expect update.actual &&
774 test_cmp post-receive.expect post-receive.actual &&
775 test_cmp post-update.expect post-update.actual
776 )
777 '
778
779 test_expect_success 'deletion of a non-existent ref alone does trigger post-receive and post-update hooks' '
780 mk_test_with_hooks testrepo heads/main &&
781 git push testrepo :refs/heads/nonexistent &&
782 (
783 cd testrepo/.git &&
784 cat >pre-receive.expect <<-EOF &&
785 $ZERO_OID $ZERO_OID refs/heads/nonexistent
786 EOF
787
788 cat >update.expect <<-EOF &&
789 refs/heads/nonexistent $ZERO_OID $ZERO_OID
790 EOF
791
792 test_cmp pre-receive.expect pre-receive.actual &&
793 test_cmp update.expect update.actual &&
794 test_path_is_missing post-receive.actual &&
795 test_path_is_missing post-update.actual
796 )
797 '
798
799 test_expect_success 'mixed ref updates, deletes, invalid deletes trigger hooks with correct input' '
800 mk_test_with_hooks testrepo heads/main heads/next heads/seen &&
801 orgmain=$(cd testrepo && git show-ref -s --verify refs/heads/main) &&
802 newmain=$(git show-ref -s --verify refs/heads/main) &&
803 orgnext=$(cd testrepo && git show-ref -s --verify refs/heads/next) &&
804 newnext=$ZERO_OID &&
805 orgseen=$(cd testrepo && git show-ref -s --verify refs/heads/seen) &&
806 newseen=$(git show-ref -s --verify refs/heads/main) &&
807 git push testrepo refs/heads/main:refs/heads/main \
808 refs/heads/main:refs/heads/seen :refs/heads/next \
809 :refs/heads/nonexistent &&
810 (
811 cd testrepo/.git &&
812 cat >pre-receive.expect <<-EOF &&
813 $orgmain $newmain refs/heads/main
814 $orgnext $newnext refs/heads/next
815 $orgseen $newseen refs/heads/seen
816 $ZERO_OID $ZERO_OID refs/heads/nonexistent
817 EOF
818
819 cat >update.expect <<-EOF &&
820 refs/heads/main $orgmain $newmain
821 refs/heads/next $orgnext $newnext
822 refs/heads/seen $orgseen $newseen
823 refs/heads/nonexistent $ZERO_OID $ZERO_OID
824 EOF
825
826 cat >post-receive.expect <<-EOF &&
827 $orgmain $newmain refs/heads/main
828 $orgnext $newnext refs/heads/next
829 $orgseen $newseen refs/heads/seen
830 EOF
831
832 cat >post-update.expect <<-EOF &&
833 refs/heads/main
834 refs/heads/next
835 refs/heads/seen
836 EOF
837
838 test_cmp pre-receive.expect pre-receive.actual &&
839 test_cmp update.expect update.actual &&
840 test_cmp post-receive.expect post-receive.actual &&
841 test_cmp post-update.expect post-update.actual
842 )
843 '
844
845 test_expect_success 'allow deleting a ref using --delete' '
846 mk_test testrepo heads/main &&
847 (cd testrepo && git config receive.denyDeleteCurrent warn) &&
848 git push testrepo --delete main &&
849 (cd testrepo && test_must_fail git rev-parse --verify refs/heads/main)
850 '
851
852 test_expect_success 'allow deleting a tag using --delete' '
853 mk_test testrepo heads/main &&
854 git tag -a -m dummy_message deltag heads/main &&
855 git push testrepo --tags &&
856 (cd testrepo && git rev-parse --verify -q refs/tags/deltag) &&
857 git push testrepo --delete tag deltag &&
858 (cd testrepo && test_must_fail git rev-parse --verify refs/tags/deltag)
859 '
860
861 test_expect_success 'push --delete without args aborts' '
862 mk_test testrepo heads/main &&
863 test_must_fail git push testrepo --delete
864 '
865
866 test_expect_success 'push --delete refuses src:dest refspecs' '
867 mk_test testrepo heads/main &&
868 test_must_fail git push testrepo --delete main:foo
869 '
870
871 test_expect_success 'push --delete refuses empty string' '
872 mk_test testrepo heads/master &&
873 test_must_fail git push testrepo --delete ""
874 '
875
876 test_expect_success 'warn on push to HEAD of non-bare repository' '
877 mk_test testrepo heads/main &&
878 (
879 cd testrepo &&
880 git checkout main &&
881 git config receive.denyCurrentBranch warn
882 ) &&
883 git push testrepo main 2>stderr &&
884 grep "warning: updating the current branch" stderr
885 '
886
887 test_expect_success 'deny push to HEAD of non-bare repository' '
888 mk_test testrepo heads/main &&
889 (
890 cd testrepo &&
891 git checkout main &&
892 git config receive.denyCurrentBranch true
893 ) &&
894 test_must_fail git push testrepo main
895 '
896
897 test_expect_success 'allow push to HEAD of bare repository (bare)' '
898 mk_test testrepo heads/main &&
899 (
900 cd testrepo &&
901 git checkout main &&
902 git config receive.denyCurrentBranch true &&
903 git config core.bare true
904 ) &&
905 git push testrepo main 2>stderr &&
906 ! grep "warning: updating the current branch" stderr
907 '
908
909 test_expect_success 'allow push to HEAD of non-bare repository (config)' '
910 mk_test testrepo heads/main &&
911 (
912 cd testrepo &&
913 git checkout main &&
914 git config receive.denyCurrentBranch false
915 ) &&
916 git push testrepo main 2>stderr &&
917 ! grep "warning: updating the current branch" stderr
918 '
919
920 test_expect_success 'fetch with branches' '
921 mk_empty testrepo &&
922 git branch second $the_first_commit &&
923 git checkout second &&
924 echo ".." > testrepo/.git/branches/branch1 &&
925 (
926 cd testrepo &&
927 git fetch branch1 &&
928 echo "$the_commit commit refs/heads/branch1" >expect &&
929 git for-each-ref refs/heads >actual &&
930 test_cmp expect actual
931 ) &&
932 git checkout main
933 '
934
935 test_expect_success 'fetch with branches containing #' '
936 mk_empty testrepo &&
937 echo "..#second" > testrepo/.git/branches/branch2 &&
938 (
939 cd testrepo &&
940 git fetch branch2 &&
941 echo "$the_first_commit commit refs/heads/branch2" >expect &&
942 git for-each-ref refs/heads >actual &&
943 test_cmp expect actual
944 ) &&
945 git checkout main
946 '
947
948 test_expect_success 'push with branches' '
949 mk_empty testrepo &&
950 git checkout second &&
951 echo "testrepo" > .git/branches/branch1 &&
952 git push branch1 &&
953 (
954 cd testrepo &&
955 echo "$the_first_commit commit refs/heads/main" >expect &&
956 git for-each-ref refs/heads >actual &&
957 test_cmp expect actual
958 )
959 '
960
961 test_expect_success 'push with branches containing #' '
962 mk_empty testrepo &&
963 echo "testrepo#branch3" > .git/branches/branch2 &&
964 git push branch2 &&
965 (
966 cd testrepo &&
967 echo "$the_first_commit commit refs/heads/branch3" >expect &&
968 git for-each-ref refs/heads >actual &&
969 test_cmp expect actual
970 ) &&
971 git checkout main
972 '
973
974 test_expect_success 'push into aliased refs (consistent)' '
975 mk_test testrepo heads/main &&
976 mk_child testrepo child1 &&
977 mk_child testrepo child2 &&
978 (
979 cd child1 &&
980 git branch foo &&
981 git symbolic-ref refs/heads/bar refs/heads/foo &&
982 git config receive.denyCurrentBranch false
983 ) &&
984 (
985 cd child2 &&
986 >path2 &&
987 git add path2 &&
988 test_tick &&
989 git commit -a -m child2 &&
990 git branch foo &&
991 git branch bar &&
992 git push ../child1 foo bar
993 )
994 '
995
996 test_expect_success 'push into aliased refs (inconsistent)' '
997 mk_test testrepo heads/main &&
998 mk_child testrepo child1 &&
999 mk_child testrepo child2 &&
1000 (
1001 cd child1 &&
1002 git branch foo &&
1003 git symbolic-ref refs/heads/bar refs/heads/foo &&
1004 git config receive.denyCurrentBranch false
1005 ) &&
1006 (
1007 cd child2 &&
1008 >path2 &&
1009 git add path2 &&
1010 test_tick &&
1011 git commit -a -m child2 &&
1012 git branch foo &&
1013 >path3 &&
1014 git add path3 &&
1015 test_tick &&
1016 git commit -a -m child2 &&
1017 git branch bar &&
1018 test_must_fail git push ../child1 foo bar 2>stderr &&
1019 grep "refusing inconsistent update" stderr
1020 )
1021 '
1022
1023 test_force_push_tag () {
1024 tag_type_description=$1
1025 tag_args=$2
1026
1027 test_expect_success "force pushing required to update $tag_type_description" "
1028 mk_test testrepo heads/main &&
1029 mk_child testrepo child1 &&
1030 mk_child testrepo child2 &&
1031 (
1032 cd child1 &&
1033 git tag testTag &&
1034 git push ../child2 testTag &&
1035 >file1 &&
1036 git add file1 &&
1037 git commit -m 'file1' &&
1038 git tag $tag_args testTag &&
1039 test_must_fail git push ../child2 testTag &&
1040 git push --force ../child2 testTag &&
1041 git tag $tag_args testTag HEAD~ &&
1042 test_must_fail git push ../child2 testTag &&
1043 git push --force ../child2 testTag &&
1044
1045 # Clobbering without + in refspec needs --force
1046 git tag -f testTag &&
1047 test_must_fail git push ../child2 'refs/tags/*:refs/tags/*' &&
1048 git push --force ../child2 'refs/tags/*:refs/tags/*' &&
1049
1050 # Clobbering with + in refspec does not need --force
1051 git tag -f testTag HEAD~ &&
1052 git push ../child2 '+refs/tags/*:refs/tags/*' &&
1053
1054 # Clobbering with --no-force still obeys + in refspec
1055 git tag -f testTag &&
1056 git push --no-force ../child2 '+refs/tags/*:refs/tags/*' &&
1057
1058 # Clobbering with/without --force and 'tag <name>' format
1059 git tag -f testTag HEAD~ &&
1060 test_must_fail git push ../child2 tag testTag &&
1061 git push --force ../child2 tag testTag
1062 )
1063 "
1064 }
1065
1066 test_force_push_tag "lightweight tag" "-f"
1067 test_force_push_tag "annotated tag" "-f -a -m'tag message'"
1068
1069 test_force_fetch_tag () {
1070 tag_type_description=$1
1071 tag_args=$2
1072
1073 test_expect_success "fetch will not clobber an existing $tag_type_description without --force" "
1074 mk_test testrepo heads/main &&
1075 mk_child testrepo child1 &&
1076 mk_child testrepo child2 &&
1077 (
1078 cd testrepo &&
1079 git tag testTag &&
1080 git -C ../child1 fetch origin tag testTag &&
1081 >file1 &&
1082 git add file1 &&
1083 git commit -m 'file1' &&
1084 git tag $tag_args testTag &&
1085 test_must_fail git -C ../child1 fetch origin tag testTag &&
1086 git -C ../child1 fetch origin '+refs/tags/*:refs/tags/*'
1087 )
1088 "
1089 }
1090
1091 test_force_fetch_tag "lightweight tag" "-f"
1092 test_force_fetch_tag "annotated tag" "-f -a -m'tag message'"
1093
1094 test_expect_success 'push --porcelain' '
1095 mk_empty testrepo &&
1096 echo >.git/foo "To testrepo" &&
1097 echo >>.git/foo "* refs/heads/main:refs/remotes/origin/main [new reference]" &&
1098 echo >>.git/foo "Done" &&
1099 git push >.git/bar --porcelain testrepo refs/heads/main:refs/remotes/origin/main &&
1100 (
1101 cd testrepo &&
1102 echo "$the_commit commit refs/remotes/origin/main" >expect &&
1103 git for-each-ref refs/remotes/origin >actual &&
1104 test_cmp expect actual
1105 ) &&
1106 test_cmp .git/foo .git/bar
1107 '
1108
1109 test_expect_success 'push --porcelain bad url' '
1110 mk_empty testrepo &&
1111 test_must_fail git push >.git/bar --porcelain asdfasdfasd refs/heads/main:refs/remotes/origin/main &&
1112 ! grep -q Done .git/bar
1113 '
1114
1115 test_expect_success 'push --porcelain rejected' '
1116 mk_empty testrepo &&
1117 git push testrepo refs/heads/main:refs/remotes/origin/main &&
1118 (cd testrepo &&
1119 git reset --hard origin/main^ &&
1120 git config receive.denyCurrentBranch true) &&
1121
1122 echo >.git/foo "To testrepo" &&
1123 echo >>.git/foo "! refs/heads/main:refs/heads/main [remote rejected] (branch is currently checked out)" &&
1124 echo >>.git/foo "Done" &&
1125
1126 test_must_fail git push >.git/bar --porcelain testrepo refs/heads/main:refs/heads/main &&
1127 test_cmp .git/foo .git/bar
1128 '
1129
1130 test_expect_success 'push --porcelain --dry-run rejected' '
1131 mk_empty testrepo &&
1132 git push testrepo refs/heads/main:refs/remotes/origin/main &&
1133 (cd testrepo &&
1134 git reset --hard origin/main &&
1135 git config receive.denyCurrentBranch true) &&
1136
1137 echo >.git/foo "To testrepo" &&
1138 echo >>.git/foo "! refs/heads/main^:refs/heads/main [rejected] (non-fast-forward)" &&
1139 echo >>.git/foo "Done" &&
1140
1141 test_must_fail git push >.git/bar --porcelain --dry-run testrepo refs/heads/main^:refs/heads/main &&
1142 test_cmp .git/foo .git/bar
1143 '
1144
1145 test_expect_success 'push --prune' '
1146 mk_test testrepo heads/main heads/second heads/foo heads/bar &&
1147 git push --prune testrepo : &&
1148 check_push_result testrepo $the_commit heads/main &&
1149 check_push_result testrepo $the_first_commit heads/second &&
1150 ! check_push_result testrepo $the_first_commit heads/foo heads/bar
1151 '
1152
1153 test_expect_success 'push --prune refspec' '
1154 mk_test testrepo tmp/main tmp/second tmp/foo tmp/bar &&
1155 git push --prune testrepo "refs/heads/*:refs/tmp/*" &&
1156 check_push_result testrepo $the_commit tmp/main &&
1157 check_push_result testrepo $the_first_commit tmp/second &&
1158 ! check_push_result testrepo $the_first_commit tmp/foo tmp/bar
1159 '
1160
1161 for configsection in transfer receive
1162 do
1163 test_expect_success "push to update a ref hidden by $configsection.hiderefs" '
1164 mk_test testrepo heads/main hidden/one hidden/two hidden/three &&
1165 (
1166 cd testrepo &&
1167 git config $configsection.hiderefs refs/hidden
1168 ) &&
1169
1170 # push to unhidden ref succeeds normally
1171 git push testrepo main:refs/heads/main &&
1172 check_push_result testrepo $the_commit heads/main &&
1173
1174 # push to update a hidden ref should fail
1175 test_must_fail git push testrepo main:refs/hidden/one &&
1176 check_push_result testrepo $the_first_commit hidden/one &&
1177
1178 # push to delete a hidden ref should fail
1179 test_must_fail git push testrepo :refs/hidden/two &&
1180 check_push_result testrepo $the_first_commit hidden/two &&
1181
1182 # idempotent push to update a hidden ref should fail
1183 test_must_fail git push testrepo $the_first_commit:refs/hidden/three &&
1184 check_push_result testrepo $the_first_commit hidden/three
1185 '
1186 done
1187
1188 test_expect_success 'fetch exact SHA1' '
1189 mk_test testrepo heads/main hidden/one &&
1190 git push testrepo main:refs/hidden/one &&
1191 (
1192 cd testrepo &&
1193 git config transfer.hiderefs refs/hidden
1194 ) &&
1195 check_push_result testrepo $the_commit hidden/one &&
1196
1197 mk_child testrepo child &&
1198 (
1199 cd child &&
1200
1201 # make sure $the_commit does not exist here
1202 git repack -a -d &&
1203 git prune &&
1204 test_must_fail git cat-file -t $the_commit &&
1205
1206 # Some protocol versions (e.g. 2) support fetching
1207 # unadvertised objects, so restrict this test to v0.
1208
1209 # fetching the hidden object should fail by default
1210 test_must_fail env GIT_TEST_PROTOCOL_VERSION=0 \
1211 git fetch -v ../testrepo $the_commit:refs/heads/copy 2>err &&
1212 test_i18ngrep "Server does not allow request for unadvertised object" err &&
1213 test_must_fail git rev-parse --verify refs/heads/copy &&
1214
1215 # the server side can allow it to succeed
1216 (
1217 cd ../testrepo &&
1218 git config uploadpack.allowtipsha1inwant true
1219 ) &&
1220
1221 git fetch -v ../testrepo $the_commit:refs/heads/copy main:refs/heads/extra &&
1222 cat >expect <<-EOF &&
1223 $the_commit
1224 $the_first_commit
1225 EOF
1226 {
1227 git rev-parse --verify refs/heads/copy &&
1228 git rev-parse --verify refs/heads/extra
1229 } >actual &&
1230 test_cmp expect actual
1231 )
1232 '
1233
1234 test_expect_success 'fetch exact SHA1 in protocol v2' '
1235 mk_test testrepo heads/main hidden/one &&
1236 git push testrepo main:refs/hidden/one &&
1237 git -C testrepo config transfer.hiderefs refs/hidden &&
1238 check_push_result testrepo $the_commit hidden/one &&
1239
1240 mk_child testrepo child &&
1241 git -C child config protocol.version 2 &&
1242
1243 # make sure $the_commit does not exist here
1244 git -C child repack -a -d &&
1245 git -C child prune &&
1246 test_must_fail git -C child cat-file -t $the_commit &&
1247
1248 # fetching the hidden object succeeds by default
1249 # NEEDSWORK: should this match the v0 behavior instead?
1250 git -C child fetch -v ../testrepo $the_commit:refs/heads/copy
1251 '
1252
1253 for configallowtipsha1inwant in true false
1254 do
1255 test_expect_success "shallow fetch reachable SHA1 (but not a ref), allowtipsha1inwant=$configallowtipsha1inwant" '
1256 mk_empty testrepo &&
1257 (
1258 cd testrepo &&
1259 git config uploadpack.allowtipsha1inwant $configallowtipsha1inwant &&
1260 git commit --allow-empty -m foo &&
1261 git commit --allow-empty -m bar
1262 ) &&
1263 SHA1=$(git --git-dir=testrepo/.git rev-parse HEAD^) &&
1264 mk_empty shallow &&
1265 (
1266 cd shallow &&
1267 # Some protocol versions (e.g. 2) support fetching
1268 # unadvertised objects, so restrict this test to v0.
1269 test_must_fail env GIT_TEST_PROTOCOL_VERSION=0 \
1270 git fetch --depth=1 ../testrepo/.git $SHA1 &&
1271 git --git-dir=../testrepo/.git config uploadpack.allowreachablesha1inwant true &&
1272 git fetch --depth=1 ../testrepo/.git $SHA1 &&
1273 git cat-file commit $SHA1
1274 )
1275 '
1276
1277 test_expect_success "deny fetch unreachable SHA1, allowtipsha1inwant=$configallowtipsha1inwant" '
1278 mk_empty testrepo &&
1279 (
1280 cd testrepo &&
1281 git config uploadpack.allowtipsha1inwant $configallowtipsha1inwant &&
1282 git commit --allow-empty -m foo &&
1283 git commit --allow-empty -m bar &&
1284 git commit --allow-empty -m xyz
1285 ) &&
1286 SHA1_1=$(git --git-dir=testrepo/.git rev-parse HEAD^^) &&
1287 SHA1_2=$(git --git-dir=testrepo/.git rev-parse HEAD^) &&
1288 SHA1_3=$(git --git-dir=testrepo/.git rev-parse HEAD) &&
1289 (
1290 cd testrepo &&
1291 git reset --hard $SHA1_2 &&
1292 git cat-file commit $SHA1_1 &&
1293 git cat-file commit $SHA1_3
1294 ) &&
1295 mk_empty shallow &&
1296 (
1297 cd shallow &&
1298 # Some protocol versions (e.g. 2) support fetching
1299 # unadvertised objects, so restrict this test to v0.
1300 test_must_fail env GIT_TEST_PROTOCOL_VERSION=0 \
1301 git fetch ../testrepo/.git $SHA1_3 &&
1302 test_must_fail env GIT_TEST_PROTOCOL_VERSION=0 \
1303 git fetch ../testrepo/.git $SHA1_1 &&
1304 git --git-dir=../testrepo/.git config uploadpack.allowreachablesha1inwant true &&
1305 git fetch ../testrepo/.git $SHA1_1 &&
1306 git cat-file commit $SHA1_1 &&
1307 test_must_fail git cat-file commit $SHA1_2 &&
1308 git fetch ../testrepo/.git $SHA1_2 &&
1309 git cat-file commit $SHA1_2 &&
1310 test_must_fail env GIT_TEST_PROTOCOL_VERSION=0 \
1311 git fetch ../testrepo/.git $SHA1_3 2>err &&
1312 # ideally we would insist this be on a "remote error:"
1313 # line, but it is racy; see the commit message
1314 test_i18ngrep "not our ref.*$SHA1_3\$" err
1315 )
1316 '
1317 done
1318
1319 test_expect_success 'fetch follows tags by default' '
1320 mk_test testrepo heads/main &&
1321 rm -fr src dst &&
1322 git init src &&
1323 (
1324 cd src &&
1325 git pull ../testrepo main &&
1326 git tag -m "annotated" tag &&
1327 git for-each-ref >tmp1 &&
1328 sed -n "p; s|refs/heads/main$|refs/remotes/origin/main|p" tmp1 |
1329 sort -k 3 >../expect
1330 ) &&
1331 git init dst &&
1332 (
1333 cd dst &&
1334 git remote add origin ../src &&
1335 git config branch.main.remote origin &&
1336 git config branch.main.merge refs/heads/main &&
1337 git pull &&
1338 git for-each-ref >../actual
1339 ) &&
1340 test_cmp expect actual
1341 '
1342
1343 test_expect_success 'peeled advertisements are not considered ref tips' '
1344 mk_empty testrepo &&
1345 git -C testrepo commit --allow-empty -m one &&
1346 git -C testrepo commit --allow-empty -m two &&
1347 git -C testrepo tag -m foo mytag HEAD^ &&
1348 oid=$(git -C testrepo rev-parse mytag^{commit}) &&
1349 test_must_fail env GIT_TEST_PROTOCOL_VERSION=0 \
1350 git fetch testrepo $oid 2>err &&
1351 test_i18ngrep "Server does not allow request for unadvertised object" err
1352 '
1353
1354 test_expect_success 'pushing a specific ref applies remote.$name.push as refmap' '
1355 mk_test testrepo heads/main &&
1356 rm -fr src dst &&
1357 git init src &&
1358 git init --bare dst &&
1359 (
1360 cd src &&
1361 git pull ../testrepo main &&
1362 git branch next &&
1363 git config remote.dst.url ../dst &&
1364 git config remote.dst.push "+refs/heads/*:refs/remotes/src/*" &&
1365 git push dst main &&
1366 git show-ref refs/heads/main |
1367 sed -e "s|refs/heads/|refs/remotes/src/|" >../dst/expect
1368 ) &&
1369 (
1370 cd dst &&
1371 test_must_fail git show-ref refs/heads/next &&
1372 test_must_fail git show-ref refs/heads/main &&
1373 git show-ref refs/remotes/src/main >actual
1374 ) &&
1375 test_cmp dst/expect dst/actual
1376 '
1377
1378 test_expect_success 'with no remote.$name.push, it is not used as refmap' '
1379 mk_test testrepo heads/main &&
1380 rm -fr src dst &&
1381 git init src &&
1382 git init --bare dst &&
1383 (
1384 cd src &&
1385 git pull ../testrepo main &&
1386 git branch next &&
1387 git config remote.dst.url ../dst &&
1388 git config push.default matching &&
1389 git push dst main &&
1390 git show-ref refs/heads/main >../dst/expect
1391 ) &&
1392 (
1393 cd dst &&
1394 test_must_fail git show-ref refs/heads/next &&
1395 git show-ref refs/heads/main >actual
1396 ) &&
1397 test_cmp dst/expect dst/actual
1398 '
1399
1400 test_expect_success 'with no remote.$name.push, upstream mapping is used' '
1401 mk_test testrepo heads/main &&
1402 rm -fr src dst &&
1403 git init src &&
1404 git init --bare dst &&
1405 (
1406 cd src &&
1407 git pull ../testrepo main &&
1408 git branch next &&
1409 git config remote.dst.url ../dst &&
1410 git config remote.dst.fetch "+refs/heads/*:refs/remotes/dst/*" &&
1411 git config push.default upstream &&
1412
1413 git config branch.main.merge refs/heads/trunk &&
1414 git config branch.main.remote dst &&
1415
1416 git push dst main &&
1417 git show-ref refs/heads/main |
1418 sed -e "s|refs/heads/main|refs/heads/trunk|" >../dst/expect
1419 ) &&
1420 (
1421 cd dst &&
1422 test_must_fail git show-ref refs/heads/main &&
1423 test_must_fail git show-ref refs/heads/next &&
1424 git show-ref refs/heads/trunk >actual
1425 ) &&
1426 test_cmp dst/expect dst/actual
1427 '
1428
1429 test_expect_success 'push does not follow tags by default' '
1430 mk_test testrepo heads/main &&
1431 rm -fr src dst &&
1432 git init src &&
1433 git init --bare dst &&
1434 (
1435 cd src &&
1436 git pull ../testrepo main &&
1437 git tag -m "annotated" tag &&
1438 git checkout -b another &&
1439 git commit --allow-empty -m "future commit" &&
1440 git tag -m "future" future &&
1441 git checkout main &&
1442 git for-each-ref refs/heads/main >../expect &&
1443 git push ../dst main
1444 ) &&
1445 (
1446 cd dst &&
1447 git for-each-ref >../actual
1448 ) &&
1449 test_cmp expect actual
1450 '
1451
1452 test_expect_success 'push --follow-tags only pushes relevant tags' '
1453 mk_test testrepo heads/main &&
1454 rm -fr src dst &&
1455 git init src &&
1456 git init --bare dst &&
1457 (
1458 cd src &&
1459 git pull ../testrepo main &&
1460 git tag -m "annotated" tag &&
1461 git checkout -b another &&
1462 git commit --allow-empty -m "future commit" &&
1463 git tag -m "future" future &&
1464 git checkout main &&
1465 git for-each-ref refs/heads/main refs/tags/tag >../expect &&
1466 git push --follow-tags ../dst main
1467 ) &&
1468 (
1469 cd dst &&
1470 git for-each-ref >../actual
1471 ) &&
1472 test_cmp expect actual
1473 '
1474
1475 test_expect_success 'push --no-thin must produce non-thin pack' '
1476 cat >>path1 <<\EOF &&
1477 keep base version of path1 big enough, compared to the new changes
1478 later, in order to pass size heuristics in
1479 builtin/pack-objects.c:try_delta()
1480 EOF
1481 git commit -am initial &&
1482 git init no-thin &&
1483 git --git-dir=no-thin/.git config receive.unpacklimit 0 &&
1484 git push no-thin/.git refs/heads/main:refs/heads/foo &&
1485 echo modified >> path1 &&
1486 git commit -am modified &&
1487 git repack -adf &&
1488 rcvpck="git receive-pack --reject-thin-pack-for-testing" &&
1489 git push --no-thin --receive-pack="$rcvpck" no-thin/.git refs/heads/main:refs/heads/foo
1490 '
1491
1492 test_expect_success 'pushing a tag pushes the tagged object' '
1493 rm -rf dst.git &&
1494 blob=$(echo unreferenced | git hash-object -w --stdin) &&
1495 git tag -m foo tag-of-blob $blob &&
1496 git init --bare dst.git &&
1497 git push dst.git tag-of-blob &&
1498 # the receiving index-pack should have noticed
1499 # any problems, but we double check
1500 echo unreferenced >expect &&
1501 git --git-dir=dst.git cat-file blob tag-of-blob >actual &&
1502 test_cmp expect actual
1503 '
1504
1505 test_expect_success 'push into bare respects core.logallrefupdates' '
1506 rm -rf dst.git &&
1507 git init --bare dst.git &&
1508 git -C dst.git config core.logallrefupdates true &&
1509
1510 # double push to test both with and without
1511 # the actual pack transfer
1512 git push dst.git main:one &&
1513 echo "one@{0} push" >expect &&
1514 git -C dst.git log -g --format="%gd %gs" one >actual &&
1515 test_cmp expect actual &&
1516
1517 git push dst.git main:two &&
1518 echo "two@{0} push" >expect &&
1519 git -C dst.git log -g --format="%gd %gs" two >actual &&
1520 test_cmp expect actual
1521 '
1522
1523 test_expect_success 'fetch into bare respects core.logallrefupdates' '
1524 rm -rf dst.git &&
1525 git init --bare dst.git &&
1526 (
1527 cd dst.git &&
1528 git config core.logallrefupdates true &&
1529
1530 # as above, we double-fetch to test both
1531 # with and without pack transfer
1532 git fetch .. main:one &&
1533 echo "one@{0} fetch .. main:one: storing head" >expect &&
1534 git log -g --format="%gd %gs" one >actual &&
1535 test_cmp expect actual &&
1536
1537 git fetch .. main:two &&
1538 echo "two@{0} fetch .. main:two: storing head" >expect &&
1539 git log -g --format="%gd %gs" two >actual &&
1540 test_cmp expect actual
1541 )
1542 '
1543
1544 test_expect_success 'receive.denyCurrentBranch = updateInstead' '
1545 git push testrepo main &&
1546 (
1547 cd testrepo &&
1548 git reset --hard &&
1549 git config receive.denyCurrentBranch updateInstead
1550 ) &&
1551 test_commit third path2 &&
1552
1553 # Try pushing into a repository with pristine working tree
1554 git push testrepo main &&
1555 (
1556 cd testrepo &&
1557 git update-index -q --refresh &&
1558 git diff-files --quiet -- &&
1559 git diff-index --quiet --cached HEAD -- &&
1560 test third = "$(cat path2)" &&
1561 test $(git -C .. rev-parse HEAD) = $(git rev-parse HEAD)
1562 ) &&
1563
1564 # Try pushing into a repository with working tree needing a refresh
1565 (
1566 cd testrepo &&
1567 git reset --hard HEAD^ &&
1568 test $(git -C .. rev-parse HEAD^) = $(git rev-parse HEAD) &&
1569 test-tool chmtime +100 path1
1570 ) &&
1571 git push testrepo main &&
1572 (
1573 cd testrepo &&
1574 git update-index -q --refresh &&
1575 git diff-files --quiet -- &&
1576 git diff-index --quiet --cached HEAD -- &&
1577 test_cmp ../path1 path1 &&
1578 test third = "$(cat path2)" &&
1579 test $(git -C .. rev-parse HEAD) = $(git rev-parse HEAD)
1580 ) &&
1581
1582 # Update what is to be pushed
1583 test_commit fourth path2 &&
1584
1585 # Try pushing into a repository with a dirty working tree
1586 # (1) the working tree updated
1587 (
1588 cd testrepo &&
1589 echo changed >path1
1590 ) &&
1591 test_must_fail git push testrepo main &&
1592 (
1593 cd testrepo &&
1594 test $(git -C .. rev-parse HEAD^) = $(git rev-parse HEAD) &&
1595 git diff --quiet --cached &&
1596 test changed = "$(cat path1)"
1597 ) &&
1598
1599 # (2) the index updated
1600 (
1601 cd testrepo &&
1602 echo changed >path1 &&
1603 git add path1
1604 ) &&
1605 test_must_fail git push testrepo main &&
1606 (
1607 cd testrepo &&
1608 test $(git -C .. rev-parse HEAD^) = $(git rev-parse HEAD) &&
1609 git diff --quiet &&
1610 test changed = "$(cat path1)"
1611 ) &&
1612
1613 # Introduce a new file in the update
1614 test_commit fifth path3 &&
1615
1616 # (3) the working tree has an untracked file that would interfere
1617 (
1618 cd testrepo &&
1619 git reset --hard &&
1620 echo changed >path3
1621 ) &&
1622 test_must_fail git push testrepo main &&
1623 (
1624 cd testrepo &&
1625 test $(git -C .. rev-parse HEAD^^) = $(git rev-parse HEAD) &&
1626 git diff --quiet &&
1627 git diff --quiet --cached &&
1628 test changed = "$(cat path3)"
1629 ) &&
1630
1631 # (4) the target changes to what gets pushed but it still is a change
1632 (
1633 cd testrepo &&
1634 git reset --hard &&
1635 echo fifth >path3 &&
1636 git add path3
1637 ) &&
1638 test_must_fail git push testrepo main &&
1639 (
1640 cd testrepo &&
1641 test $(git -C .. rev-parse HEAD^^) = $(git rev-parse HEAD) &&
1642 git diff --quiet &&
1643 test fifth = "$(cat path3)"
1644 ) &&
1645
1646 # (5) push into void
1647 rm -fr void &&
1648 git init void &&
1649 (
1650 cd void &&
1651 git config receive.denyCurrentBranch updateInstead
1652 ) &&
1653 git push void main &&
1654 (
1655 cd void &&
1656 test $(git -C .. rev-parse main) = $(git rev-parse HEAD) &&
1657 git diff --quiet &&
1658 git diff --cached --quiet
1659 ) &&
1660
1661 # (6) updateInstead intervened by fast-forward check
1662 test_must_fail git push void main^:main &&
1663 test $(git -C void rev-parse HEAD) = $(git rev-parse main) &&
1664 git -C void diff --quiet &&
1665 git -C void diff --cached --quiet
1666 '
1667
1668 test_expect_success 'updateInstead with push-to-checkout hook' '
1669 rm -fr testrepo &&
1670 git init testrepo &&
1671 (
1672 cd testrepo &&
1673 git pull .. main &&
1674 git reset --hard HEAD^^ &&
1675 git tag initial &&
1676 git config receive.denyCurrentBranch updateInstead &&
1677 write_script .git/hooks/push-to-checkout <<-\EOF
1678 echo >&2 updating from $(git rev-parse HEAD)
1679 echo >&2 updating to "$1"
1680
1681 git update-index -q --refresh &&
1682 git read-tree -u -m HEAD "$1" || {
1683 status=$?
1684 echo >&2 read-tree failed
1685 exit $status
1686 }
1687 EOF
1688 ) &&
1689
1690 # Try pushing into a pristine
1691 git push testrepo main &&
1692 (
1693 cd testrepo &&
1694 git diff --quiet &&
1695 git diff HEAD --quiet &&
1696 test $(git -C .. rev-parse HEAD) = $(git rev-parse HEAD)
1697 ) &&
1698
1699 # Try pushing into a repository with conflicting change
1700 (
1701 cd testrepo &&
1702 git reset --hard initial &&
1703 echo conflicting >path2
1704 ) &&
1705 test_must_fail git push testrepo main &&
1706 (
1707 cd testrepo &&
1708 test $(git rev-parse initial) = $(git rev-parse HEAD) &&
1709 test conflicting = "$(cat path2)" &&
1710 git diff-index --quiet --cached HEAD
1711 ) &&
1712
1713 # Try pushing into a repository with unrelated change
1714 (
1715 cd testrepo &&
1716 git reset --hard initial &&
1717 echo unrelated >path1 &&
1718 echo irrelevant >path5 &&
1719 git add path5
1720 ) &&
1721 git push testrepo main &&
1722 (
1723 cd testrepo &&
1724 test "$(cat path1)" = unrelated &&
1725 test "$(cat path5)" = irrelevant &&
1726 test "$(git diff --name-only --cached HEAD)" = path5 &&
1727 test $(git -C .. rev-parse HEAD) = $(git rev-parse HEAD)
1728 ) &&
1729
1730 # push into void
1731 rm -fr void &&
1732 git init void &&
1733 (
1734 cd void &&
1735 git config receive.denyCurrentBranch updateInstead &&
1736 write_script .git/hooks/push-to-checkout <<-\EOF
1737 if git rev-parse --quiet --verify HEAD
1738 then
1739 has_head=yes
1740 echo >&2 updating from $(git rev-parse HEAD)
1741 else
1742 has_head=no
1743 echo >&2 pushing into void
1744 fi
1745 echo >&2 updating to "$1"
1746
1747 git update-index -q --refresh &&
1748 case "$has_head" in
1749 yes)
1750 git read-tree -u -m HEAD "$1" ;;
1751 no)
1752 git read-tree -u -m "$1" ;;
1753 esac || {
1754 status=$?
1755 echo >&2 read-tree failed
1756 exit $status
1757 }
1758 EOF
1759 ) &&
1760
1761 git push void main &&
1762 (
1763 cd void &&
1764 git diff --quiet &&
1765 git diff --cached --quiet &&
1766 test $(git -C .. rev-parse HEAD) = $(git rev-parse HEAD)
1767 )
1768 '
1769
1770 test_expect_success 'denyCurrentBranch and worktrees' '
1771 git worktree add new-wt &&
1772 git clone . cloned &&
1773 test_commit -C cloned first &&
1774 test_config receive.denyCurrentBranch refuse &&
1775 test_must_fail git -C cloned push origin HEAD:new-wt &&
1776 test_config receive.denyCurrentBranch updateInstead &&
1777 git -C cloned push origin HEAD:new-wt &&
1778 test_path_exists new-wt/first.t &&
1779 test_must_fail git -C cloned push --delete origin new-wt
1780 '
1781
1782 test_expect_success 'denyCurrentBranch and bare repository worktrees' '
1783 test_when_finished "rm -fr bare.git" &&
1784 git clone --bare . bare.git &&
1785 git -C bare.git worktree add wt &&
1786 test_commit grape &&
1787 git -C bare.git config receive.denyCurrentBranch refuse &&
1788 test_must_fail git push bare.git HEAD:wt &&
1789 git -C bare.git config receive.denyCurrentBranch updateInstead &&
1790 git push bare.git HEAD:wt &&
1791 test_path_exists bare.git/wt/grape.t &&
1792 test_must_fail git push --delete bare.git wt
1793 '
1794
1795 test_expect_success 'refuse fetch to current branch of worktree' '
1796 test_when_finished "git worktree remove --force wt && git branch -D wt" &&
1797 git worktree add wt &&
1798 test_commit apple &&
1799 test_must_fail git fetch . HEAD:wt &&
1800 git fetch -u . HEAD:wt
1801 '
1802
1803 test_expect_success 'refuse fetch to current branch of bare repository worktree' '
1804 test_when_finished "rm -fr bare.git" &&
1805 git clone --bare . bare.git &&
1806 git -C bare.git worktree add wt &&
1807 test_commit banana &&
1808 test_must_fail git -C bare.git fetch .. HEAD:wt &&
1809 git -C bare.git fetch -u .. HEAD:wt
1810 '
1811
1812 test_done