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