Raw
1 #!/bin/sh
2
3 test_description='git remote porcelain-ish'
4
5 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
6 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
7
8 . ./test-lib.sh
9
10 setup_repository () {
11 mkdir "$1" && (
12 cd "$1" &&
13 git init -b main &&
14 >file &&
15 git add file &&
16 test_tick &&
17 git commit -m "Initial" &&
18 git checkout -b side &&
19 >elif &&
20 git add elif &&
21 test_tick &&
22 git commit -m "Second" &&
23 git checkout main
24 )
25 }
26
27 tokens_match () {
28 echo "$1" | tr ' ' '\012' | sort | sed -e '/^$/d' >expect &&
29 echo "$2" | tr ' ' '\012' | sort | sed -e '/^$/d' >actual &&
30 test_cmp expect actual
31 }
32
33 check_remote_track () {
34 actual=$(git remote show "$1" | sed -ne 's|^ \(.*\) tracked$|\1|p')
35 shift &&
36 tokens_match "$*" "$actual"
37 }
38
39 check_tracking_branch () {
40 f="" &&
41 r=$(git for-each-ref "--format=%(refname)" |
42 sed -ne "s|^refs/remotes/$1/||p") &&
43 shift &&
44 tokens_match "$*" "$r"
45 }
46
47 test_expect_success setup '
48 setup_repository one &&
49 setup_repository two &&
50 (
51 cd two &&
52 git branch another
53 ) &&
54 git clone one test
55 '
56
57 test_expect_success 'add remote whose URL agrees with url.<...>.insteadOf' '
58 test_config url.git@host.com:team/repo.git.insteadOf myremote &&
59 git remote add myremote git@host.com:team/repo.git
60 '
61
62 test_expect_success 'remote information for the origin' '
63 (
64 cd test &&
65 tokens_match origin "$(git remote)" &&
66 check_remote_track origin main side &&
67 check_tracking_branch origin HEAD main side
68 )
69 '
70
71 test_expect_success 'add another remote' '
72 (
73 cd test &&
74 git remote add -f second ../two &&
75 tokens_match "origin second" "$(git remote)" &&
76 check_tracking_branch second main side another HEAD &&
77 git for-each-ref "--format=%(refname)" refs/remotes |
78 sed -e "/^refs\/remotes\/origin\//d" \
79 -e "/^refs\/remotes\/second\//d" >actual &&
80 test_must_be_empty actual
81 )
82 '
83
84 test_expect_success 'setup bare clone for server' '
85 git clone --bare "file://$(pwd)/one" srv.bare &&
86 git -C srv.bare config --local uploadpack.allowfilter 1 &&
87 git -C srv.bare config --local uploadpack.allowanysha1inwant 1
88 '
89
90 test_expect_success 'filters for promisor remotes are listed by git remote -v' '
91 test_when_finished "rm -rf pc" &&
92 git clone --filter=blob:none "file://$(pwd)/srv.bare" pc &&
93 git -C pc remote -v >out &&
94 grep "srv.bare (fetch) \[blob:none\]" out &&
95
96 git -C pc config remote.origin.partialCloneFilter object:type=commit &&
97 git -C pc remote -v >out &&
98 grep "srv.bare (fetch) \[object:type=commit\]" out
99 '
100
101 test_expect_success 'filters should not be listed for non promisor remotes (remote -v)' '
102 test_when_finished "rm -rf pc" &&
103 git clone one pc &&
104 git -C pc remote -v >out &&
105 ! grep "(fetch) \[.*\]" out
106 '
107
108 test_expect_success 'filters are listed by git remote -v only' '
109 test_when_finished "rm -rf pc" &&
110 git clone --filter=blob:none "file://$(pwd)/srv.bare" pc &&
111 git -C pc remote >out &&
112 ! grep "\[blob:none\]" out &&
113
114 git -C pc remote show >out &&
115 ! grep "\[blob:none\]" out
116 '
117
118 test_expect_success 'check remote-tracking' '
119 (
120 cd test &&
121 check_remote_track origin main side &&
122 check_remote_track second main side another
123 )
124 '
125
126 test_expect_success 'remote forces tracking branches' '
127 (
128 cd test &&
129 case $(git config remote.second.fetch) in
130 +*) true ;;
131 *) false ;;
132 esac
133 )
134 '
135
136 test_expect_success 'remove remote' '
137 (
138 cd test &&
139 git symbolic-ref refs/remotes/second/HEAD refs/remotes/second/main &&
140 git remote rm second
141 )
142 '
143
144 test_expect_success 'remove remote' '
145 (
146 cd test &&
147 tokens_match origin "$(git remote)" &&
148 check_remote_track origin main side &&
149 git for-each-ref "--format=%(refname)" refs/remotes |
150 sed -e "/^refs\/remotes\/origin\//d" >actual &&
151 test_must_be_empty actual
152 )
153 '
154
155 test_expect_success 'remove remote protects local branches' '
156 (
157 cd test &&
158 cat >expect1 <<-\EOF &&
159 Note: A branch outside the refs/remotes/ hierarchy was not removed;
160 to delete it, use:
161 git branch -d main
162 EOF
163 cat >expect2 <<-\EOF &&
164 Note: Some branches outside the refs/remotes/ hierarchy were not removed;
165 to delete them, use:
166 git branch -d foobranch
167 git branch -d main
168 EOF
169 git tag footag &&
170 git config --add remote.oops.fetch "+refs/*:refs/*" &&
171 git remote remove oops 2>actual1 &&
172 git branch foobranch &&
173 git config --add remote.oops.fetch "+refs/*:refs/*" &&
174 git remote rm oops 2>actual2 &&
175 git branch -d foobranch &&
176 git tag -d footag &&
177 test_cmp expect1 actual1 &&
178 test_cmp expect2 actual2
179 )
180 '
181
182 test_expect_success 'remove errors out early when deleting non-existent branch' '
183 (
184 cd test &&
185 echo "error: No such remote: '\''foo'\''" >expect &&
186 test_expect_code 2 git remote rm foo 2>actual &&
187 test_cmp expect actual
188 )
189 '
190
191 test_expect_success 'remove remote with a branch without configured merge' '
192 test_when_finished "(
193 git -C test checkout main;
194 git -C test branch -D two;
195 git -C test config --remove-section remote.two;
196 git -C test config --remove-section branch.second;
197 true
198 )" &&
199 (
200 cd test &&
201 git remote add two ../two &&
202 git fetch two &&
203 git checkout -b second two/main^0 &&
204 git config branch.second.remote two &&
205 git checkout main &&
206 git remote rm two
207 )
208 '
209
210 test_expect_success 'rename errors out early when deleting non-existent branch' '
211 (
212 cd test &&
213 echo "error: No such remote: '\''foo'\''" >expect &&
214 test_expect_code 2 git remote rename foo bar 2>actual &&
215 test_cmp expect actual
216 )
217 '
218
219 test_expect_success 'rename errors out early when new name is invalid' '
220 test_config remote.foo.vcs bar &&
221 echo "fatal: '\''invalid...name'\'' is not a valid remote name" >expect &&
222 test_must_fail git remote rename foo invalid...name 2>actual &&
223 test_cmp expect actual
224 '
225
226 test_expect_success 'add existing foreign_vcs remote' '
227 test_config remote.foo.vcs bar &&
228 echo "error: remote foo already exists." >expect &&
229 test_expect_code 3 git remote add foo bar 2>actual &&
230 test_cmp expect actual
231 '
232
233 test_expect_success 'add existing foreign_vcs remote' '
234 test_config remote.foo.vcs bar &&
235 test_config remote.bar.vcs bar &&
236 echo "error: remote bar already exists." >expect &&
237 test_expect_code 3 git remote rename foo bar 2>actual &&
238 test_cmp expect actual
239 '
240
241 test_expect_success 'add invalid foreign_vcs remote' '
242 echo "fatal: '\''invalid...name'\'' is not a valid remote name" >expect &&
243 test_must_fail git remote add invalid...name bar 2>actual &&
244 test_cmp expect actual
245 '
246
247 test_expect_success 'without subcommand' '
248 echo origin >expect &&
249 git -C test remote >actual &&
250 test_cmp expect actual
251 '
252
253 test_expect_success 'without subcommand accepts -v' '
254 cat >expect <<-EOF &&
255 origin $(pwd)/one (fetch)
256 origin $(pwd)/one (push)
257 EOF
258 git -C test remote -v >actual &&
259 test_cmp expect actual
260 '
261
262 test_expect_success 'without subcommand does not take arguments' '
263 test_expect_code 129 git -C test remote origin 2>err &&
264 grep "^error: unknown subcommand:" err
265 '
266
267 cat >test/expect <<EOF
268 * remote origin
269 Fetch URL: $(pwd)/one
270 Push URL: $(pwd)/one
271 HEAD branch: main
272 Remote branches:
273 main new (next fetch will store in remotes/origin)
274 side tracked
275 Local branches configured for 'git pull':
276 ahead merges with remote main
277 main merges with remote main
278 octopus merges with remote topic-a
279 and with remote topic-b
280 and with remote topic-c
281 rebase rebases onto remote main
282 Local refs configured for 'git push':
283 main pushes to main (local out of date)
284 main pushes to upstream (create)
285 * remote two
286 Fetch URL: ../two
287 Push URL: ../three
288 HEAD branch: main
289 Local refs configured for 'git push':
290 ahead forces to main (fast-forwardable)
291 main pushes to another (up to date)
292 EOF
293
294 test_expect_success 'show' '
295 (
296 cd test &&
297 git config --add remote.origin.fetch refs/heads/main:refs/heads/upstream &&
298 git fetch &&
299 git checkout -b ahead origin/main &&
300 echo 1 >>file &&
301 test_tick &&
302 git commit -m update file &&
303 git checkout main &&
304 git branch --track octopus origin/main &&
305 git branch --track rebase origin/main &&
306 git branch -d -r origin/main &&
307 git config --add remote.two.url ../two &&
308 git config --add remote.two.pushurl ../three &&
309 git config branch.rebase.rebase true &&
310 git config branch.octopus.merge "topic-a topic-b topic-c" &&
311 (
312 cd ../one &&
313 echo 1 >file &&
314 test_tick &&
315 git commit -m update file
316 ) &&
317 git config --add remote.origin.push : &&
318 git config --add remote.origin.push refs/heads/main:refs/heads/upstream &&
319 git config --add remote.origin.push +refs/tags/lastbackup &&
320 git config --add remote.two.push +refs/heads/ahead:refs/heads/main &&
321 git config --add remote.two.push refs/heads/main:refs/heads/another &&
322 git remote show origin two >output &&
323 git branch -d rebase octopus &&
324 test_cmp expect output
325 )
326 '
327
328 cat >expect <<EOF
329 * remote origin
330 Fetch URL: $(pwd)/one
331 Push URL: $(pwd)/one
332 HEAD branch: main
333 Remote branches:
334 main skipped
335 side tracked
336 Local branches configured for 'git pull':
337 ahead merges with remote main
338 main merges with remote main
339 Local refs configured for 'git push':
340 main pushes to main (local out of date)
341 main pushes to upstream (create)
342 EOF
343
344 test_expect_success 'show with negative refspecs' '
345 test_when_finished "git -C test config --unset-all --fixed-value remote.origin.fetch ^refs/heads/main" &&
346 git -C test config --add remote.origin.fetch ^refs/heads/main &&
347 git -C test remote show origin >output &&
348 test_cmp expect output
349 '
350
351 cat >expect <<EOF
352 * remote origin
353 Fetch URL: $(pwd)/one
354 Push URL: $(pwd)/one
355 HEAD branch: main
356 Remote branches:
357 main new (next fetch will store in remotes/origin)
358 side stale (use 'git remote prune' to remove)
359 Local branches configured for 'git pull':
360 ahead merges with remote main
361 main merges with remote main
362 Local refs configured for 'git push':
363 main pushes to main (local out of date)
364 main pushes to upstream (create)
365 EOF
366
367 test_expect_failure 'show stale with negative refspecs' '
368 test_when_finished "git -C test config --unset-all --fixed-value remote.origin.fetch ^refs/heads/side" &&
369 git -C test config --add remote.origin.fetch ^refs/heads/side &&
370 git -C test remote show origin >output &&
371 test_cmp expect output
372 '
373
374 cat >test/expect <<EOF
375 * remote origin
376 Fetch URL: $(pwd)/one
377 Push URL: $(pwd)/one
378 HEAD branch: (not queried)
379 Remote branches: (status not queried)
380 main
381 side
382 Local branches configured for 'git pull':
383 ahead merges with remote main
384 main merges with remote main
385 Local refs configured for 'git push' (status not queried):
386 (matching) pushes to (matching)
387 refs/heads/main pushes to refs/heads/upstream
388 refs/tags/lastbackup forces to refs/tags/lastbackup
389 EOF
390
391 test_expect_success 'show -n' '
392 mv one one.unreachable &&
393 (
394 cd test &&
395 git remote show -n origin >output &&
396 mv ../one.unreachable ../one &&
397 test_cmp expect output
398 )
399 '
400
401 test_expect_success 'prune' '
402 (
403 cd one &&
404 git branch -m side side2
405 ) &&
406 (
407 cd test &&
408 git fetch origin &&
409 git remote prune origin &&
410 git rev-parse refs/remotes/origin/side2 &&
411 test_must_fail git rev-parse refs/remotes/origin/side
412 )
413 '
414
415 test_expect_success 'set-head --delete' '
416 (
417 cd test &&
418 git symbolic-ref refs/remotes/origin/HEAD &&
419 git remote set-head --delete origin &&
420 test_must_fail git symbolic-ref refs/remotes/origin/HEAD
421 )
422 '
423
424 test_expect_success 'set-head --auto' '
425 (
426 cd test &&
427 git remote set-head --auto origin &&
428 echo refs/remotes/origin/main >expect &&
429 git symbolic-ref refs/remotes/origin/HEAD >output &&
430 test_cmp expect output
431 )
432 '
433
434 test_expect_success REFFILES 'set-head --auto failure' '
435 test_when_finished "rm -f test/.git/refs/remotes/origin/HEAD.lock" &&
436 (
437 cd test &&
438 touch .git/refs/remotes/origin/HEAD.lock &&
439 test_must_fail git remote set-head --auto origin 2>err &&
440 tail -n1 err >output &&
441 echo "error: Could not set up refs/remotes/origin/HEAD" >expect &&
442 test_cmp expect output
443 )
444 '
445
446 test_expect_success 'set-head --auto detects creation' '
447 (
448 cd test &&
449 git update-ref --no-deref -d refs/remotes/origin/HEAD &&
450 git remote set-head --auto origin >output &&
451 echo "${SQ}origin/HEAD${SQ} is now created and points to ${SQ}main${SQ}" >expect &&
452 test_cmp expect output
453 )
454 '
455
456 test_expect_success 'set-head --auto to update a non symbolic ref' '
457 (
458 cd test &&
459 git update-ref --no-deref -d refs/remotes/origin/HEAD &&
460 git update-ref refs/remotes/origin/HEAD HEAD &&
461 HEAD=$(git log --pretty="%H") &&
462 git remote set-head --auto origin >output &&
463 echo "${SQ}origin/HEAD${SQ} was detached at ${SQ}${HEAD}${SQ} and now points to ${SQ}main${SQ}" >expect &&
464 test_cmp expect output
465 )
466 '
467
468 test_expect_success 'set-head --auto detects no change' '
469 (
470 cd test &&
471 git remote set-head --auto origin >output &&
472 echo "${SQ}origin/HEAD${SQ} is unchanged and points to ${SQ}main${SQ}" >expect &&
473 test_cmp expect output
474 )
475 '
476
477 test_expect_success 'set-head --auto detects change' '
478 (
479 cd test &&
480 git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/ahead &&
481 git remote set-head --auto origin >output &&
482 echo "${SQ}origin/HEAD${SQ} has changed from ${SQ}ahead${SQ} and now points to ${SQ}main${SQ}" >expect &&
483 test_cmp expect output
484 )
485 '
486
487 test_expect_success 'set-head --auto detects strange ref' '
488 (
489 cd test &&
490 git symbolic-ref refs/remotes/origin/HEAD refs/heads/main &&
491 git remote set-head --auto origin >output &&
492 echo "${SQ}origin/HEAD${SQ} used to point to ${SQ}refs/heads/main${SQ} (which is not a remote branch), but now points to ${SQ}main${SQ}" >expect &&
493 test_cmp expect output
494 )
495 '
496
497 test_expect_success 'set-head --auto has no problem w/multiple HEADs' '
498 (
499 cd test &&
500 git fetch two "refs/heads/*:refs/remotes/two/*" &&
501 git remote set-head --auto two >output 2>&1 &&
502 echo "${SQ}two/HEAD${SQ} is now created and points to ${SQ}main${SQ}" >expect &&
503 test_cmp expect output
504 )
505 '
506
507 test_expect_success 'set-head changes followRemoteHEAD always to warn' '
508 (
509 cd test &&
510 git config set remote.origin.followRemoteHEAD "always" &&
511 git remote set-head --auto origin &&
512 git config get remote.origin.followRemoteHEAD >actual &&
513 echo "warn" >expect &&
514 test_cmp expect actual
515 )
516 '
517
518 cat >test/expect <<\EOF
519 refs/remotes/origin/side2
520 EOF
521
522 test_expect_success 'set-head explicit' '
523 (
524 cd test &&
525 git remote set-head origin side2 &&
526 git symbolic-ref refs/remotes/origin/HEAD >output &&
527 git remote set-head origin main &&
528 test_cmp expect output
529 )
530 '
531
532 test_expect_success 'set-head --auto reports change' '
533 (
534 cd test &&
535 git remote set-head origin side2 &&
536 git remote set-head --auto origin >output 2>&1 &&
537 echo "${SQ}origin/HEAD${SQ} has changed from ${SQ}side2${SQ} and now points to ${SQ}main${SQ}" >expect &&
538 test_cmp expect output
539 )
540 '
541
542 cat >test/expect <<EOF
543 Pruning origin
544 URL: $(pwd)/one
545 * [would prune] origin/side2
546 EOF
547
548 test_expect_success 'prune --dry-run' '
549 git -C one branch -m side2 side &&
550 test_when_finished "git -C one branch -m side side2" &&
551 (
552 cd test &&
553 git remote prune --dry-run origin >output &&
554 git rev-parse refs/remotes/origin/side2 &&
555 test_must_fail git rev-parse refs/remotes/origin/side &&
556 test_cmp expect output
557 )
558 '
559
560 test_expect_success 'add --mirror && prune' '
561 mkdir mirror &&
562 (
563 cd mirror &&
564 git init --bare &&
565 git remote add --mirror -f origin ../one
566 ) &&
567 (
568 cd one &&
569 git branch -m side2 side
570 ) &&
571 (
572 cd mirror &&
573 git rev-parse --verify refs/heads/side2 &&
574 test_must_fail git rev-parse --verify refs/heads/side &&
575 git fetch origin &&
576 git remote prune origin &&
577 test_must_fail git rev-parse --verify refs/heads/side2 &&
578 git rev-parse --verify refs/heads/side
579 )
580 '
581
582 test_expect_success 'add --mirror setting HEAD' '
583 mkdir headmirror &&
584 (
585 cd headmirror &&
586 git init --bare -b notmain &&
587 git remote add --mirror -f origin ../one &&
588 test "$(git symbolic-ref HEAD)" = "refs/heads/main"
589 )
590 '
591
592 test_expect_success 'non-mirror fetch does not interfere with mirror' '
593 test_when_finished rm -rf headnotmain &&
594 (
595 git init --bare -b notmain headnotmain &&
596 cd headnotmain &&
597 git remote add -f other ../two &&
598 test "$(git symbolic-ref HEAD)" = "refs/heads/notmain"
599 )
600 '
601
602 test_expect_success 'add --mirror=fetch' '
603 mkdir mirror-fetch &&
604 git init -b main mirror-fetch/parent &&
605 (
606 cd mirror-fetch/parent &&
607 test_commit one
608 ) &&
609 git init --bare mirror-fetch/child &&
610 (
611 cd mirror-fetch/child &&
612 git remote add --mirror=fetch -f parent ../parent
613 )
614 '
615
616 test_expect_success 'fetch mirrors act as mirrors during fetch' '
617 (
618 cd mirror-fetch/parent &&
619 git branch new &&
620 git branch -m main renamed
621 ) &&
622 (
623 cd mirror-fetch/child &&
624 git fetch parent &&
625 git rev-parse --verify refs/heads/new &&
626 git rev-parse --verify refs/heads/renamed
627 )
628 '
629
630 test_expect_success 'fetch mirrors can prune' '
631 (
632 cd mirror-fetch/child &&
633 git remote prune parent &&
634 test_must_fail git rev-parse --verify refs/heads/main
635 )
636 '
637
638 test_expect_success 'fetch mirrors do not act as mirrors during push' '
639 (
640 cd mirror-fetch/parent &&
641 git checkout HEAD^0
642 ) &&
643 (
644 cd mirror-fetch/child &&
645 git branch -m renamed renamed2 &&
646 git push parent :
647 ) &&
648 (
649 cd mirror-fetch/parent &&
650 git rev-parse --verify renamed &&
651 test_must_fail git rev-parse --verify refs/heads/renamed2
652 )
653 '
654
655 test_expect_success 'add fetch mirror with specific branches' '
656 git init --bare mirror-fetch/track &&
657 (
658 cd mirror-fetch/track &&
659 git remote add --mirror=fetch -t heads/new parent ../parent
660 )
661 '
662
663 test_expect_success 'fetch mirror respects specific branches' '
664 (
665 cd mirror-fetch/track &&
666 git fetch parent &&
667 git rev-parse --verify refs/heads/new &&
668 test_must_fail git rev-parse --verify refs/heads/renamed
669 )
670 '
671
672 test_expect_success 'add --mirror=push' '
673 mkdir mirror-push &&
674 git init --bare mirror-push/public &&
675 git init -b main mirror-push/private &&
676 (
677 cd mirror-push/private &&
678 test_commit one &&
679 git remote add --mirror=push public ../public
680 )
681 '
682
683 test_expect_success 'push mirrors act as mirrors during push' '
684 (
685 cd mirror-push/private &&
686 git branch new &&
687 git branch -m main renamed &&
688 git push public
689 ) &&
690 (
691 cd mirror-push/private &&
692 git rev-parse --verify refs/heads/new &&
693 git rev-parse --verify refs/heads/renamed &&
694 test_must_fail git rev-parse --verify refs/heads/main
695 )
696 '
697
698 test_expect_success 'push mirrors do not act as mirrors during fetch' '
699 (
700 cd mirror-push/public &&
701 git branch -m renamed renamed2 &&
702 git symbolic-ref HEAD refs/heads/renamed2
703 ) &&
704 (
705 cd mirror-push/private &&
706 git fetch public &&
707 git rev-parse --verify refs/heads/renamed &&
708 test_must_fail git rev-parse --verify refs/heads/renamed2
709 )
710 '
711
712 test_expect_success 'push mirrors do not allow you to specify refs' '
713 git init mirror-push/track &&
714 (
715 cd mirror-push/track &&
716 test_must_fail git remote add --mirror=push -t new public ../public
717 )
718 '
719
720 test_expect_success 'add alt && prune' '
721 mkdir alttst &&
722 (
723 cd alttst &&
724 git init &&
725 git remote add -f origin ../one &&
726 git config remote.alt.url ../one &&
727 git config remote.alt.fetch "+refs/heads/*:refs/remotes/origin/*"
728 ) &&
729 (
730 cd one &&
731 git branch -m side side2
732 ) &&
733 (
734 cd alttst &&
735 git rev-parse --verify refs/remotes/origin/side &&
736 test_must_fail git rev-parse --verify refs/remotes/origin/side2 &&
737 git fetch alt &&
738 git remote prune alt &&
739 test_must_fail git rev-parse --verify refs/remotes/origin/side &&
740 git rev-parse --verify refs/remotes/origin/side2
741 )
742 '
743
744 cat >test/expect <<\EOF
745 some-tag
746 EOF
747
748 test_expect_success 'add with reachable tags (default)' '
749 (
750 cd one &&
751 >foobar &&
752 git add foobar &&
753 git commit -m "Foobar" &&
754 git tag -a -m "Foobar tag" foobar-tag &&
755 git reset --hard HEAD~1 &&
756 git tag -a -m "Some tag" some-tag
757 ) &&
758 mkdir add-tags &&
759 (
760 cd add-tags &&
761 git init &&
762 git remote add -f origin ../one &&
763 git tag -l some-tag >../test/output &&
764 git tag -l foobar-tag >>../test/output &&
765 test_must_fail git config remote.origin.tagopt
766 ) &&
767 test_cmp test/expect test/output
768 '
769
770 cat >test/expect <<\EOF
771 some-tag
772 foobar-tag
773 --tags
774 EOF
775
776 test_expect_success 'add --tags' '
777 rm -rf add-tags &&
778 (
779 mkdir add-tags &&
780 cd add-tags &&
781 git init &&
782 git remote add -f --tags origin ../one &&
783 git tag -l some-tag >../test/output &&
784 git tag -l foobar-tag >>../test/output &&
785 git config remote.origin.tagopt >>../test/output
786 ) &&
787 test_cmp test/expect test/output
788 '
789
790 cat >test/expect <<\EOF
791 --no-tags
792 EOF
793
794 test_expect_success 'add --no-tags' '
795 rm -rf add-tags &&
796 (
797 mkdir add-no-tags &&
798 cd add-no-tags &&
799 git init &&
800 git remote add -f --no-tags origin ../one &&
801 grep tagOpt .git/config &&
802 git tag -l some-tag >../test/output &&
803 git tag -l foobar-tag >../test/output &&
804 git config remote.origin.tagopt >>../test/output
805 ) &&
806 (
807 cd one &&
808 git tag -d some-tag foobar-tag
809 ) &&
810 test_cmp test/expect test/output
811 '
812
813 test_expect_success 'reject --no-no-tags' '
814 (
815 cd add-no-tags &&
816 test_must_fail git remote add -f --no-no-tags neworigin ../one
817 )
818 '
819
820 cat >one/expect <<\EOF
821 apis/HEAD -> apis/main
822 apis/main
823 apis/side
824 drosophila/HEAD -> drosophila/main
825 drosophila/another
826 drosophila/main
827 drosophila/side
828 EOF
829
830 test_expect_success 'update' '
831 (
832 cd one &&
833 git remote add drosophila ../two &&
834 git remote add apis ../mirror &&
835 git remote update &&
836 git branch -r >output &&
837 test_cmp expect output
838 )
839 '
840
841 cat >one/expect <<\EOF
842 drosophila/HEAD -> drosophila/main
843 drosophila/another
844 drosophila/main
845 drosophila/side
846 manduca/HEAD -> manduca/main
847 manduca/main
848 manduca/side
849 megaloprepus/HEAD -> megaloprepus/main
850 megaloprepus/main
851 megaloprepus/side
852 EOF
853
854 test_expect_success 'update with arguments' '
855 (
856 cd one &&
857 for b in $(git branch -r | grep -v HEAD)
858 do
859 git branch -r -d $b || exit 1
860 done &&
861 git remote add manduca ../mirror &&
862 git remote add megaloprepus ../mirror &&
863 git config remotes.phobaeticus "drosophila megaloprepus" &&
864 git config remotes.titanus manduca &&
865 git remote update phobaeticus titanus &&
866 git branch -r >output &&
867 test_cmp expect output
868 )
869 '
870
871 test_expect_success 'update --prune' '
872 (
873 cd one &&
874 git branch -m side2 side3
875 ) &&
876 (
877 cd test &&
878 git remote update --prune &&
879 (
880 cd ../one &&
881 git branch -m side3 side2
882 ) &&
883 git rev-parse refs/remotes/origin/side3 &&
884 test_must_fail git rev-parse refs/remotes/origin/side2
885 )
886 '
887
888 cat >one/expect <<-\EOF
889 apis/HEAD -> apis/main
890 apis/main
891 apis/side
892 manduca/HEAD -> manduca/main
893 manduca/main
894 manduca/side
895 megaloprepus/HEAD -> megaloprepus/main
896 megaloprepus/main
897 megaloprepus/side
898 EOF
899
900 test_expect_success 'update default' '
901 (
902 cd one &&
903 for b in $(git branch -r | grep -v HEAD)
904 do
905 git branch -r -d $b || exit 1
906 done &&
907 git config remote.drosophila.skipDefaultUpdate true &&
908 git remote update default &&
909 git branch -r >output &&
910 test_cmp expect output
911 )
912 '
913
914 cat >one/expect <<\EOF
915 drosophila/HEAD -> drosophila/main
916 drosophila/another
917 drosophila/main
918 drosophila/side
919 EOF
920
921 test_expect_success 'update default (overridden, with funny whitespace)' '
922 (
923 cd one &&
924 for b in $(git branch -r | grep -v HEAD)
925 do
926 git branch -r -d $b || exit 1
927 done &&
928 git config remotes.default "$(printf "\t drosophila \n")" &&
929 git remote update default &&
930 git branch -r >output &&
931 test_cmp expect output
932 )
933 '
934
935 test_expect_success 'update (with remotes.default defined)' '
936 (
937 cd one &&
938 for b in $(git branch -r | grep -v HEAD)
939 do
940 git branch -r -d $b || exit 1
941 done &&
942 git config remotes.default "drosophila" &&
943 git remote update &&
944 git branch -r >output &&
945 test_cmp expect output
946 )
947 '
948
949 test_expect_success '"remote show" does not show symbolic refs' '
950 git clone one three &&
951 (
952 cd three &&
953 git remote show origin >output &&
954 ! grep "^ *HEAD$" < output &&
955 ! grep -i stale < output
956 )
957 '
958
959 test_expect_success 'reject adding remote with an invalid name' '
960 test_must_fail git remote add some:url desired-name
961 '
962
963 # The first three test if the tracking branches are properly renamed,
964 # the last two ones check if the config is updated.
965
966 test_expect_success 'rename a remote' '
967 test_config_global remote.pushDefault origin &&
968 git clone one four &&
969 (
970 cd four &&
971 git config branch.main.pushRemote origin &&
972 GIT_TRACE2_EVENT=$(pwd)/trace \
973 git remote rename --progress origin upstream &&
974 test_region progress "Renaming remote references" trace &&
975 grep "pushRemote" .git/config &&
976 test -z "$(git for-each-ref refs/remotes/origin)" &&
977 test "$(git symbolic-ref refs/remotes/upstream/HEAD)" = "refs/remotes/upstream/main" &&
978 test "$(git rev-parse upstream/main)" = "$(git rev-parse main)" &&
979 test "$(git config remote.upstream.fetch)" = "+refs/heads/*:refs/remotes/upstream/*" &&
980 test "$(git config branch.main.remote)" = "upstream" &&
981 test "$(git config branch.main.pushRemote)" = "upstream" &&
982 test "$(git config --global remote.pushDefault)" = "origin"
983 )
984 '
985
986 test_expect_success 'rename a remote renames repo remote.pushDefault' '
987 git clone one four.1 &&
988 (
989 cd four.1 &&
990 git config remote.pushDefault origin &&
991 git remote rename origin upstream &&
992 grep pushDefault .git/config &&
993 test "$(git config --local remote.pushDefault)" = "upstream"
994 )
995 '
996
997 test_expect_success 'rename a remote renames repo remote.pushDefault but ignores global' '
998 test_config_global remote.pushDefault other &&
999 git clone one four.2 &&
1000 (
1001 cd four.2 &&
1002 git config remote.pushDefault origin &&
1003 git remote rename origin upstream &&
1004 test "$(git config --global remote.pushDefault)" = "other" &&
1005 test "$(git config --local remote.pushDefault)" = "upstream"
1006 )
1007 '
1008
1009 test_expect_success 'rename a remote renames repo remote.pushDefault but keeps global' '
1010 test_config_global remote.pushDefault origin &&
1011 git clone one four.3 &&
1012 (
1013 cd four.3 &&
1014 git config remote.pushDefault origin &&
1015 git remote rename origin upstream &&
1016 test "$(git config --global remote.pushDefault)" = "origin" &&
1017 test "$(git config --local remote.pushDefault)" = "upstream"
1018 )
1019 '
1020
1021 test_expect_success 'rename handles remote without fetch refspec' '
1022 git clone --bare one no-refspec.git &&
1023 # confirm assumption that bare clone does not create refspec
1024 test_expect_code 5 \
1025 git -C no-refspec.git config --unset-all remote.origin.fetch &&
1026 git -C no-refspec.git config remote.origin.url >expect &&
1027 git -C no-refspec.git remote rename origin foo &&
1028 git -C no-refspec.git config remote.foo.url >actual &&
1029 test_cmp expect actual
1030 '
1031
1032 test_expect_success 'rename does not update a non-default fetch refspec' '
1033 git clone one four.one &&
1034 (
1035 cd four.one &&
1036 git config remote.origin.fetch +refs/heads/*:refs/heads/origin/* &&
1037 git remote rename origin upstream &&
1038 test "$(git config remote.upstream.fetch)" = "+refs/heads/*:refs/heads/origin/*" &&
1039 git rev-parse -q origin/main
1040 )
1041 '
1042
1043 test_expect_success 'rename a remote with name part of fetch spec' '
1044 git clone one four.two &&
1045 (
1046 cd four.two &&
1047 git remote rename origin remote &&
1048 git remote rename remote upstream &&
1049 test "$(git config remote.upstream.fetch)" = "+refs/heads/*:refs/remotes/upstream/*"
1050 )
1051 '
1052
1053 test_expect_success 'rename a remote with name prefix of other remote' '
1054 git clone one four.three &&
1055 (
1056 cd four.three &&
1057 git remote add o git://example.com/repo.git &&
1058 git remote rename o upstream &&
1059 test "$(git rev-parse origin/main)" = "$(git rev-parse main)"
1060 )
1061 '
1062
1063 test_expect_success 'rename succeeds with existing remote.<target>.prune' '
1064 git clone one four.four &&
1065 test_when_finished git config --global --unset remote.upstream.prune &&
1066 git config --global remote.upstream.prune true &&
1067 git -C four.four remote rename origin upstream
1068 '
1069
1070 test_expect_success 'remove a remote' '
1071 test_config_global remote.pushDefault origin &&
1072 git clone one four.five &&
1073 (
1074 cd four.five &&
1075 git config branch.main.pushRemote origin &&
1076 git remote remove origin &&
1077 test -z "$(git for-each-ref refs/remotes/origin)" &&
1078 test_must_fail git config branch.main.remote &&
1079 test_must_fail git config branch.main.pushRemote &&
1080 test "$(git config --global remote.pushDefault)" = "origin"
1081 )
1082 '
1083
1084 test_expect_success 'remove a remote removes repo remote.pushDefault' '
1085 git clone one four.five.1 &&
1086 (
1087 cd four.five.1 &&
1088 git config remote.pushDefault origin &&
1089 git remote remove origin &&
1090 test_must_fail git config --local remote.pushDefault
1091 )
1092 '
1093
1094 test_expect_success 'remove a remote removes repo remote.pushDefault but ignores global' '
1095 test_config_global remote.pushDefault other &&
1096 git clone one four.five.2 &&
1097 (
1098 cd four.five.2 &&
1099 git config remote.pushDefault origin &&
1100 git remote remove origin &&
1101 test "$(git config --global remote.pushDefault)" = "other" &&
1102 test_must_fail git config --local remote.pushDefault
1103 )
1104 '
1105
1106 test_expect_success 'remove a remote removes repo remote.pushDefault but keeps global' '
1107 test_config_global remote.pushDefault origin &&
1108 git clone one four.five.3 &&
1109 (
1110 cd four.five.3 &&
1111 git config remote.pushDefault origin &&
1112 git remote remove origin &&
1113 test "$(git config --global remote.pushDefault)" = "origin" &&
1114 test_must_fail git config --local remote.pushDefault
1115 )
1116 '
1117
1118 cat >remotes_origin <<EOF
1119 URL: $(pwd)/one
1120 Push: refs/heads/main:refs/heads/upstream
1121 Push: refs/heads/next:refs/heads/upstream2
1122 Pull: refs/heads/main:refs/heads/origin
1123 Pull: refs/heads/next:refs/heads/origin2
1124 EOF
1125
1126 test_expect_success !WITH_BREAKING_CHANGES 'migrate a remote from named file in $GIT_DIR/remotes' '
1127 git clone one five &&
1128 origin_url=$(pwd)/one &&
1129 (
1130 cd five &&
1131 git remote remove origin &&
1132 mkdir -p .git/remotes &&
1133 cat ../remotes_origin >.git/remotes/origin &&
1134 git remote rename origin origin &&
1135 test_path_is_missing .git/remotes/origin &&
1136 test "$(git config remote.origin.url)" = "$origin_url" &&
1137 cat >push_expected <<-\EOF &&
1138 refs/heads/main:refs/heads/upstream
1139 refs/heads/next:refs/heads/upstream2
1140 EOF
1141 cat >fetch_expected <<-\EOF &&
1142 refs/heads/main:refs/heads/origin
1143 refs/heads/next:refs/heads/origin2
1144 EOF
1145 git config --get-all remote.origin.push >push_actual &&
1146 git config --get-all remote.origin.fetch >fetch_actual &&
1147 test_cmp push_expected push_actual &&
1148 test_cmp fetch_expected fetch_actual
1149 )
1150 '
1151
1152 test_expect_success !WITH_BREAKING_CHANGES 'migrate a remote from named file in $GIT_DIR/branches' '
1153 git clone --template= one six &&
1154 origin_url=$(pwd)/one &&
1155 (
1156 cd six &&
1157 git remote rm origin &&
1158 mkdir .git/branches &&
1159 echo "$origin_url#main" >.git/branches/origin &&
1160 git remote rename origin origin &&
1161 test_path_is_missing .git/branches/origin &&
1162 test "$(git config remote.origin.url)" = "$origin_url" &&
1163 test "$(git config remote.origin.fetch)" = "refs/heads/main:refs/heads/origin" &&
1164 test "$(git config remote.origin.push)" = "HEAD:refs/heads/main"
1165 )
1166 '
1167
1168 test_expect_success !WITH_BREAKING_CHANGES 'migrate a remote from named file in $GIT_DIR/branches (2)' '
1169 git clone --template= one seven &&
1170 (
1171 cd seven &&
1172 git remote rm origin &&
1173 mkdir .git/branches &&
1174 echo "quux#foom" > .git/branches/origin &&
1175 git remote rename origin origin &&
1176 test_path_is_missing .git/branches/origin &&
1177 test "$(git config remote.origin.url)" = "quux" &&
1178 test "$(git config remote.origin.fetch)" = "refs/heads/foom:refs/heads/origin" &&
1179 test "$(git config remote.origin.push)" = "HEAD:refs/heads/foom"
1180 )
1181 '
1182
1183 test_expect_success 'remote prune to cause a dangling symref' '
1184 git clone one eight &&
1185 (
1186 cd one &&
1187 git checkout side2 &&
1188 git branch -D main
1189 ) &&
1190 (
1191 cd eight &&
1192 git remote prune origin
1193 ) >err 2>&1 &&
1194 test_grep "has become dangling" err &&
1195
1196 : And the dangling symref will not cause other annoying errors &&
1197 (
1198 cd eight &&
1199 git branch -a
1200 ) 2>err &&
1201 ! grep "points nowhere" err &&
1202 (
1203 cd eight &&
1204 test_must_fail git branch nomore origin
1205 ) 2>err &&
1206 test_grep "dangling symref" err
1207 '
1208
1209 test_expect_success 'show empty remote' '
1210 test_create_repo empty &&
1211 git clone empty empty-clone &&
1212 (
1213 cd empty-clone &&
1214 git remote show origin
1215 )
1216 '
1217
1218 test_expect_success 'remote set-branches requires a remote' '
1219 test_must_fail git remote set-branches &&
1220 test_must_fail git remote set-branches --add
1221 '
1222
1223 test_expect_success 'remote set-branches' '
1224 echo "+refs/heads/*:refs/remotes/scratch/*" >expect.initial &&
1225 sort <<-\EOF >expect.add &&
1226 +refs/heads/*:refs/remotes/scratch/*
1227 +refs/heads/other:refs/remotes/scratch/other
1228 EOF
1229 sort <<-\EOF >expect.replace &&
1230 +refs/heads/maint:refs/remotes/scratch/maint
1231 +refs/heads/main:refs/remotes/scratch/main
1232 +refs/heads/next:refs/remotes/scratch/next
1233 EOF
1234 sort <<-\EOF >expect.add-two &&
1235 +refs/heads/maint:refs/remotes/scratch/maint
1236 +refs/heads/main:refs/remotes/scratch/main
1237 +refs/heads/next:refs/remotes/scratch/next
1238 +refs/heads/seen:refs/remotes/scratch/seen
1239 +refs/heads/t/topic:refs/remotes/scratch/t/topic
1240 EOF
1241 sort <<-\EOF >expect.setup-ffonly &&
1242 refs/heads/main:refs/remotes/scratch/main
1243 +refs/heads/next:refs/remotes/scratch/next
1244 EOF
1245 sort <<-\EOF >expect.respect-ffonly &&
1246 refs/heads/main:refs/remotes/scratch/main
1247 +refs/heads/next:refs/remotes/scratch/next
1248 +refs/heads/seen:refs/remotes/scratch/seen
1249 EOF
1250
1251 git clone .git/ setbranches &&
1252 (
1253 cd setbranches &&
1254 git remote rename origin scratch &&
1255 git config --get-all remote.scratch.fetch >config-result &&
1256 sort <config-result >../actual.initial &&
1257
1258 git remote set-branches scratch --add other &&
1259 git config --get-all remote.scratch.fetch >config-result &&
1260 sort <config-result >../actual.add &&
1261
1262 git remote set-branches scratch maint main next &&
1263 git config --get-all remote.scratch.fetch >config-result &&
1264 sort <config-result >../actual.replace &&
1265
1266 git remote set-branches --add scratch seen t/topic &&
1267 git config --get-all remote.scratch.fetch >config-result &&
1268 sort <config-result >../actual.add-two &&
1269
1270 git config --unset-all remote.scratch.fetch &&
1271 git config remote.scratch.fetch \
1272 refs/heads/main:refs/remotes/scratch/main &&
1273 git config --add remote.scratch.fetch \
1274 +refs/heads/next:refs/remotes/scratch/next &&
1275 git config --get-all remote.scratch.fetch >config-result &&
1276 sort <config-result >../actual.setup-ffonly &&
1277
1278 git remote set-branches --add scratch seen &&
1279 git config --get-all remote.scratch.fetch >config-result &&
1280 sort <config-result >../actual.respect-ffonly
1281 ) &&
1282 test_cmp expect.initial actual.initial &&
1283 test_cmp expect.add actual.add &&
1284 test_cmp expect.replace actual.replace &&
1285 test_cmp expect.add-two actual.add-two &&
1286 test_cmp expect.setup-ffonly actual.setup-ffonly &&
1287 test_cmp expect.respect-ffonly actual.respect-ffonly
1288 '
1289
1290 test_expect_success 'remote set-branches with --mirror' '
1291 echo "+refs/*:refs/*" >expect.initial &&
1292 echo "+refs/heads/main:refs/heads/main" >expect.replace &&
1293 git clone --mirror .git/ setbranches-mirror &&
1294 (
1295 cd setbranches-mirror &&
1296 git remote rename origin scratch &&
1297 git config --get-all remote.scratch.fetch >../actual.initial &&
1298
1299 git remote set-branches scratch heads/main &&
1300 git config --get-all remote.scratch.fetch >../actual.replace
1301 ) &&
1302 test_cmp expect.initial actual.initial &&
1303 test_cmp expect.replace actual.replace
1304 '
1305
1306 test_expect_success 'new remote' '
1307 git remote add someremote foo &&
1308 echo foo >expect &&
1309 git config --get-all remote.someremote.url >actual &&
1310 cmp expect actual
1311 '
1312
1313 get_url_test () {
1314 cat >expect &&
1315 git remote get-url "$@" >actual &&
1316 test_cmp expect actual
1317 }
1318
1319 test_expect_success 'get-url on new remote' '
1320 echo foo | get_url_test someremote &&
1321 echo foo | get_url_test --all someremote &&
1322 echo foo | get_url_test --push someremote &&
1323 echo foo | get_url_test --push --all someremote
1324 '
1325
1326 test_expect_success 'remote set-url with locked config' '
1327 test_when_finished "rm -f .git/config.lock" &&
1328 git config --get-all remote.someremote.url >expect &&
1329 >.git/config.lock &&
1330 test_must_fail git remote set-url someremote baz &&
1331 git config --get-all remote.someremote.url >actual &&
1332 cmp expect actual
1333 '
1334
1335 test_expect_success 'remote set-url bar' '
1336 git remote set-url someremote bar &&
1337 echo bar >expect &&
1338 git config --get-all remote.someremote.url >actual &&
1339 cmp expect actual
1340 '
1341
1342 test_expect_success 'remote set-url baz bar' '
1343 git remote set-url someremote baz bar &&
1344 echo baz >expect &&
1345 git config --get-all remote.someremote.url >actual &&
1346 cmp expect actual
1347 '
1348
1349 test_expect_success 'remote set-url zot bar' '
1350 test_must_fail git remote set-url someremote zot bar &&
1351 echo baz >expect &&
1352 git config --get-all remote.someremote.url >actual &&
1353 cmp expect actual
1354 '
1355
1356 test_expect_success 'remote set-url --push zot baz' '
1357 test_must_fail git remote set-url --push someremote zot baz &&
1358 echo "YYY" >expect &&
1359 echo baz >>expect &&
1360 test_must_fail git config --get-all remote.someremote.pushurl >actual &&
1361 echo "YYY" >>actual &&
1362 git config --get-all remote.someremote.url >>actual &&
1363 cmp expect actual
1364 '
1365
1366 test_expect_success 'remote set-url --push zot' '
1367 git remote set-url --push someremote zot &&
1368 echo zot >expect &&
1369 echo "YYY" >>expect &&
1370 echo baz >>expect &&
1371 git config --get-all remote.someremote.pushurl >actual &&
1372 echo "YYY" >>actual &&
1373 git config --get-all remote.someremote.url >>actual &&
1374 cmp expect actual
1375 '
1376
1377 test_expect_success 'get-url with different urls' '
1378 echo baz | get_url_test someremote &&
1379 echo baz | get_url_test --all someremote &&
1380 echo zot | get_url_test --push someremote &&
1381 echo zot | get_url_test --push --all someremote
1382 '
1383
1384 test_expect_success 'remote set-url --push qux zot' '
1385 git remote set-url --push someremote qux zot &&
1386 echo qux >expect &&
1387 echo "YYY" >>expect &&
1388 echo baz >>expect &&
1389 git config --get-all remote.someremote.pushurl >actual &&
1390 echo "YYY" >>actual &&
1391 git config --get-all remote.someremote.url >>actual &&
1392 cmp expect actual
1393 '
1394
1395 test_expect_success 'remote set-url --push foo qu+x' '
1396 git remote set-url --push someremote foo qu+x &&
1397 echo foo >expect &&
1398 echo "YYY" >>expect &&
1399 echo baz >>expect &&
1400 git config --get-all remote.someremote.pushurl >actual &&
1401 echo "YYY" >>actual &&
1402 git config --get-all remote.someremote.url >>actual &&
1403 cmp expect actual
1404 '
1405
1406 test_expect_success 'remote set-url --push --add aaa' '
1407 git remote set-url --push --add someremote aaa &&
1408 echo foo >expect &&
1409 echo aaa >>expect &&
1410 echo "YYY" >>expect &&
1411 echo baz >>expect &&
1412 git config --get-all remote.someremote.pushurl >actual &&
1413 echo "YYY" >>actual &&
1414 git config --get-all remote.someremote.url >>actual &&
1415 cmp expect actual
1416 '
1417
1418 test_expect_success 'get-url on multi push remote' '
1419 echo foo | get_url_test --push someremote &&
1420 get_url_test --push --all someremote <<-\EOF
1421 foo
1422 aaa
1423 EOF
1424 '
1425
1426 test_expect_success 'remote set-url --push bar aaa' '
1427 git remote set-url --push someremote bar aaa &&
1428 echo foo >expect &&
1429 echo bar >>expect &&
1430 echo "YYY" >>expect &&
1431 echo baz >>expect &&
1432 git config --get-all remote.someremote.pushurl >actual &&
1433 echo "YYY" >>actual &&
1434 git config --get-all remote.someremote.url >>actual &&
1435 cmp expect actual
1436 '
1437
1438 test_expect_success 'remote set-url --push --delete bar' '
1439 git remote set-url --push --delete someremote bar &&
1440 echo foo >expect &&
1441 echo "YYY" >>expect &&
1442 echo baz >>expect &&
1443 git config --get-all remote.someremote.pushurl >actual &&
1444 echo "YYY" >>actual &&
1445 git config --get-all remote.someremote.url >>actual &&
1446 cmp expect actual
1447 '
1448
1449 test_expect_success 'remote set-url --push --delete foo' '
1450 git remote set-url --push --delete someremote foo &&
1451 echo "YYY" >expect &&
1452 echo baz >>expect &&
1453 test_must_fail git config --get-all remote.someremote.pushurl >actual &&
1454 echo "YYY" >>actual &&
1455 git config --get-all remote.someremote.url >>actual &&
1456 cmp expect actual
1457 '
1458
1459 test_expect_success 'remote set-url --add bbb' '
1460 git remote set-url --add someremote bbb &&
1461 echo "YYY" >expect &&
1462 echo baz >>expect &&
1463 echo bbb >>expect &&
1464 test_must_fail git config --get-all remote.someremote.pushurl >actual &&
1465 echo "YYY" >>actual &&
1466 git config --get-all remote.someremote.url >>actual &&
1467 cmp expect actual
1468 '
1469
1470 test_expect_success 'get-url on multi fetch remote' '
1471 echo baz | get_url_test someremote &&
1472 get_url_test --all someremote <<-\EOF
1473 baz
1474 bbb
1475 EOF
1476 '
1477
1478 test_expect_success 'remote set-url --delete .*' '
1479 test_must_fail git remote set-url --delete someremote .\* &&
1480 echo "YYY" >expect &&
1481 echo baz >>expect &&
1482 echo bbb >>expect &&
1483 test_must_fail git config --get-all remote.someremote.pushurl >actual &&
1484 echo "YYY" >>actual &&
1485 git config --get-all remote.someremote.url >>actual &&
1486 cmp expect actual
1487 '
1488
1489 test_expect_success 'remote set-url --delete bbb' '
1490 git remote set-url --delete someremote bbb &&
1491 echo "YYY" >expect &&
1492 echo baz >>expect &&
1493 test_must_fail git config --get-all remote.someremote.pushurl >actual &&
1494 echo "YYY" >>actual &&
1495 git config --get-all remote.someremote.url >>actual &&
1496 cmp expect actual
1497 '
1498
1499 test_expect_success 'remote set-url --delete baz' '
1500 test_must_fail git remote set-url --delete someremote baz &&
1501 echo "YYY" >expect &&
1502 echo baz >>expect &&
1503 test_must_fail git config --get-all remote.someremote.pushurl >actual &&
1504 echo "YYY" >>actual &&
1505 git config --get-all remote.someremote.url >>actual &&
1506 cmp expect actual
1507 '
1508
1509 test_expect_success 'remote set-url --add ccc' '
1510 git remote set-url --add someremote ccc &&
1511 echo "YYY" >expect &&
1512 echo baz >>expect &&
1513 echo ccc >>expect &&
1514 test_must_fail git config --get-all remote.someremote.pushurl >actual &&
1515 echo "YYY" >>actual &&
1516 git config --get-all remote.someremote.url >>actual &&
1517 cmp expect actual
1518 '
1519
1520 test_expect_success 'remote set-url --delete baz' '
1521 git remote set-url --delete someremote baz &&
1522 echo "YYY" >expect &&
1523 echo ccc >>expect &&
1524 test_must_fail git config --get-all remote.someremote.pushurl >actual &&
1525 echo "YYY" >>actual &&
1526 git config --get-all remote.someremote.url >>actual &&
1527 cmp expect actual
1528 '
1529
1530 test_expect_success 'extra args: setup' '
1531 # add a dummy origin so that this does not trigger failure
1532 git remote add origin .
1533 '
1534
1535 test_extra_arg () {
1536 test_expect_success "extra args: $*" "
1537 test_must_fail git remote $* bogus_extra_arg 2>actual &&
1538 test_grep '^usage:' actual
1539 "
1540 }
1541
1542 test_extra_arg add nick url
1543 test_extra_arg rename origin newname
1544 test_extra_arg remove origin
1545 test_extra_arg set-head origin main
1546 # set-branches takes any number of args
1547 test_extra_arg get-url origin newurl
1548 test_extra_arg set-url origin newurl oldurl
1549 # show takes any number of args
1550 # prune takes any number of args
1551 # update takes any number of args
1552
1553 test_expect_success 'add remote matching the "insteadOf" URL' '
1554 git config url.xyz@example.com.insteadOf backup &&
1555 git remote add backup xyz@example.com
1556 '
1557
1558 test_expect_success 'unqualified <dst> refspec DWIM and advice' '
1559 test_when_finished "(cd test && git tag -d some-tag)" &&
1560 (
1561 cd test &&
1562 git tag -a -m "Some tag" some-tag main &&
1563 for type in commit tag tree blob
1564 do
1565 if test "$type" = "blob"
1566 then
1567 oid=$(git rev-parse some-tag:file)
1568 else
1569 oid=$(git rev-parse some-tag^{$type})
1570 fi &&
1571 test_must_fail git push origin $oid:dst 2>err &&
1572 test_grep "error: The destination you" err &&
1573 test_grep "hint: Did you mean" err &&
1574 test_must_fail git -c advice.pushUnqualifiedRefName=false \
1575 push origin $oid:dst 2>err &&
1576 test_grep "error: The destination you" err &&
1577 test_grep ! "hint: Did you mean" err ||
1578 exit 1
1579 done
1580 )
1581 '
1582
1583 test_expect_success 'refs/remotes/* <src> refspec and unqualified <dst> DWIM and advice' '
1584 (
1585 cd two &&
1586 git tag -a -m "Some tag" my-tag main &&
1587 git update-ref refs/trees/my-head-tree HEAD^{tree} &&
1588 git update-ref refs/blobs/my-file-blob HEAD:file
1589 ) &&
1590 (
1591 cd test &&
1592 git config --add remote.two.fetch "+refs/tags/*:refs/remotes/tags-from-two/*" &&
1593 git config --add remote.two.fetch "+refs/trees/*:refs/remotes/trees-from-two/*" &&
1594 git config --add remote.two.fetch "+refs/blobs/*:refs/remotes/blobs-from-two/*" &&
1595 git fetch --no-tags two &&
1596
1597 test_must_fail git push origin refs/remotes/two/another:dst 2>err &&
1598 test_grep "error: The destination you" err &&
1599
1600 test_must_fail git push origin refs/remotes/tags-from-two/my-tag:dst-tag 2>err &&
1601 test_grep "error: The destination you" err &&
1602
1603 test_must_fail git push origin refs/remotes/trees-from-two/my-head-tree:dst-tree 2>err &&
1604 test_grep "error: The destination you" err &&
1605
1606 test_must_fail git push origin refs/remotes/blobs-from-two/my-file-blob:dst-blob 2>err &&
1607 test_grep "error: The destination you" err
1608 )
1609 '
1610
1611 test_expect_success 'empty config clears remote.*.url list' '
1612 test_when_finished "git config --remove-section remote.multi" &&
1613 git config --add remote.multi.url wrong-one &&
1614 git config --add remote.multi.url wrong-two &&
1615 git -c remote.multi.url= \
1616 -c remote.multi.url=right-one \
1617 -c remote.multi.url=right-two \
1618 remote show -n multi >actual.raw &&
1619 grep URL actual.raw >actual &&
1620 cat >expect <<-\EOF &&
1621 Fetch URL: right-one
1622 Push URL: right-one
1623 Push URL: right-two
1624 EOF
1625 test_cmp expect actual
1626 '
1627
1628 test_expect_success 'empty config clears remote.*.pushurl list' '
1629 test_when_finished "git config --remove-section remote.multi" &&
1630 git config --add remote.multi.url right &&
1631 git config --add remote.multi.url will-be-ignored &&
1632 git config --add remote.multi.pushurl wrong-push-one &&
1633 git config --add remote.multi.pushurl wrong-push-two &&
1634 git -c remote.multi.pushurl= \
1635 -c remote.multi.pushurl=right-push-one \
1636 -c remote.multi.pushurl=right-push-two \
1637 remote show -n multi >actual.raw &&
1638 grep URL actual.raw >actual &&
1639 cat >expect <<-\EOF &&
1640 Fetch URL: right
1641 Push URL: right-push-one
1642 Push URL: right-push-two
1643 EOF
1644 test_cmp expect actual
1645 '
1646
1647 test_expect_success 'forbid adding subset of existing remote' '
1648 test_when_finished "git remote rm outer" &&
1649 git remote add outer url &&
1650 test_must_fail git remote add outer/inner url 2>err &&
1651 test_grep ".outer/inner. is a subset of existing remote .outer." err
1652 '
1653
1654 test_expect_success 'forbid adding superset of existing remote' '
1655 test_when_finished "git remote rm outer/inner" &&
1656 git remote add outer/inner url &&
1657 test_must_fail git remote add outer url 2>err &&
1658 test_grep ".outer. is a superset of existing remote .outer/inner." err
1659 '
1660
1661 test_expect_success 'rename handles unborn HEAD' '
1662 test_when_finished "git remote remove unborn-renamed" &&
1663 git remote add unborn url &&
1664 git symbolic-ref refs/remotes/unborn/HEAD refs/remotes/unborn/nonexistent &&
1665 git remote rename unborn unborn-renamed &&
1666 git symbolic-ref refs/remotes/unborn-renamed/HEAD >actual &&
1667 echo refs/remotes/unborn-renamed/nonexistent >expected &&
1668 test_cmp expected actual
1669 '
1670
1671 test_expect_success 'rename can nest a remote into itself' '
1672 test_commit parent-commit &&
1673 COMMIT_ID=$(git rev-parse HEAD) &&
1674 test_when_finished "git remote remove parent || true" &&
1675 git remote add parent url &&
1676 git update-ref refs/remotes/parent/branch $COMMIT_ID &&
1677 test_when_finished "git remote remove parent/child" &&
1678 git remote rename parent parent/child &&
1679 git for-each-ref refs/remotes/ >actual &&
1680 printf "$COMMIT_ID commit\trefs/remotes/parent/child/branch\n" >expected &&
1681 test_cmp expected actual
1682 '
1683
1684 test_expect_success 'rename can nest a remote into itself with a conflicting branch name' '
1685 test_commit parent-conflict &&
1686 COMMIT_ID=$(git rev-parse HEAD) &&
1687 test_when_finished "git remote remove parent || true" &&
1688 git remote add parent url &&
1689 git update-ref refs/remotes/parent/child $COMMIT_ID &&
1690 test_when_finished "git remote remove parent/child" &&
1691 test_must_fail git remote rename parent parent/child 2>err &&
1692 test_grep "renaming remote references failed" err &&
1693 test_grep "The remote you are trying to rename has conflicting references" err &&
1694 git for-each-ref refs/remotes/ >actual &&
1695 printf "$COMMIT_ID commit\trefs/remotes/parent/child\n" >expected &&
1696 test_cmp expected actual
1697 '
1698
1699 test_expect_success 'rename can unnest a remote' '
1700 test_commit parent-child-commit &&
1701 COMMIT_ID=$(git rev-parse HEAD) &&
1702 test_when_finished "git remote remove parent/child || true" &&
1703 git remote add parent/child url &&
1704 git update-ref refs/remotes/parent/child/branch $COMMIT_ID &&
1705 git remote rename parent/child parent &&
1706 git for-each-ref refs/remotes/ >actual &&
1707 printf "$COMMIT_ID commit\trefs/remotes/parent/branch\n" >expected &&
1708 test_cmp expected actual
1709 '
1710
1711 test_expect_success 'rename moves around the reflog' '
1712 test_commit reflog-old &&
1713 COMMIT_ID=$(git rev-parse HEAD) &&
1714 test_config core.logAllRefUpdates true &&
1715 test_when_finished "git remote remove reflog-old || true" &&
1716 git remote add reflog-old url &&
1717 git update-ref refs/remotes/reflog-old/branch $COMMIT_ID &&
1718 test-tool ref-store main for-each-reflog >actual &&
1719 test_grep refs/remotes/reflog-old/branch actual &&
1720 test-tool ref-store main for-each-reflog-ent refs/remotes/reflog-old/branch >reflog-entries-old &&
1721 test_line_count = 1 reflog-entries-old &&
1722 git remote rename reflog-old reflog-new &&
1723 test-tool ref-store main for-each-reflog >actual &&
1724 test_grep ! refs/remotes/reflog-old actual &&
1725 test_grep refs/remotes/reflog-new/branch actual &&
1726 test-tool ref-store main for-each-reflog-ent refs/remotes/reflog-new/branch >reflog-entries-new &&
1727 cat >expect <<-EOF &&
1728 $(cat reflog-entries-old)
1729 $COMMIT_ID $COMMIT_ID $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1112912173 -0700 remote: renamed refs/remotes/reflog-old/branch to refs/remotes/reflog-new/branch
1730 EOF
1731 test_cmp expect reflog-entries-new
1732 '
1733
1734 test_done