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