1#!/bin/sh 2# Copyright (c) 2006, Junio C Hamano. 3 4test_description='Per branch config variables affects "git fetch". 5 6' 7 8GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main 9export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 10 11. ./test-lib.sh 12. "$TEST_DIRECTORY"/lib-bundle.sh 13 14D=$(pwd) 15 16test_expect_success setup ' 17 echo >file original && 18 git add file && 19 git commit -a -m original && 20 git branch -M main 21' 22 23test_expect_success "clone and setup child repos" ' 24 git clone . one && 25 ( 26 cd one && 27 echo >file updated by one && 28 git commit -a -m "updated by one" 29 ) && 30 git clone . two && 31 ( 32 cd two && 33 git config branch.main.remote one && 34 git config remote.one.url ../one/.git/ && 35 git config remote.one.fetch refs/heads/main:refs/heads/one 36 ) && 37 git clone . three && 38 ( 39 cd three && 40 git config branch.main.remote two && 41 git config branch.main.merge refs/heads/one && 42 mkdir -p .git/remotes && 43 { 44 echo "URL: ../two/.git/" 45 echo "Pull: refs/heads/main:refs/heads/two" 46 echo "Pull: refs/heads/one:refs/heads/one" 47 } >.git/remotes/two 48 ) && 49 git clone . bundle && 50 git clone . seven 51' 52 53test_expect_success "fetch test" ' 54 cd "$D" && 55 echo >file updated by origin && 56 git commit -a -m "updated by origin" && 57 cd two && 58 git fetch && 59 git rev-parse --verify refs/heads/one && 60 mine=$(git rev-parse refs/heads/one) && 61 his=$(cd ../one && git rev-parse refs/heads/main) && 62 test "z$mine" = "z$his" 63' 64 65test_expect_success "fetch test for-merge" ' 66 cd "$D" && 67 cd three && 68 git fetch && 69 git rev-parse --verify refs/heads/two && 70 git rev-parse --verify refs/heads/one && 71 main_in_two=$(cd ../two && git rev-parse main) && 72 one_in_two=$(cd ../two && git rev-parse one) && 73 { 74 echo "$one_in_two " 75 echo "$main_in_two not-for-merge" 76 } >expected && 77 cut -f -2 .git/FETCH_HEAD >actual && 78 test_cmp expected actual' 79 80test_expect_success 'fetch --prune on its own works as expected' ' 81 cd "$D" && 82 git clone . prune && 83 cd prune && 84 git update-ref refs/remotes/origin/extrabranch main && 85 86 git fetch --prune origin && 87 test_must_fail git rev-parse origin/extrabranch 88' 89 90test_expect_success 'fetch --prune with a branch name keeps branches' ' 91 cd "$D" && 92 git clone . prune-branch && 93 cd prune-branch && 94 git update-ref refs/remotes/origin/extrabranch main && 95 96 git fetch --prune origin main && 97 git rev-parse origin/extrabranch 98' 99 100test_expect_success 'fetch --prune with a namespace keeps other namespaces' ' 101 cd "$D" && 102 git clone . prune-namespace && 103 cd prune-namespace && 104 105 git fetch --prune origin refs/heads/a/*:refs/remotes/origin/a/* && 106 git rev-parse origin/main 107' 108 109test_expect_success 'fetch --prune handles overlapping refspecs' ' 110 cd "$D" && 111 git update-ref refs/pull/42/head main && 112 git clone . prune-overlapping && 113 cd prune-overlapping && 114 git config --add remote.origin.fetch refs/pull/*/head:refs/remotes/origin/pr/* && 115 116 git fetch --prune origin && 117 git rev-parse origin/main && 118 git rev-parse origin/pr/42 && 119 120 git config --unset-all remote.origin.fetch && 121 git config remote.origin.fetch refs/pull/*/head:refs/remotes/origin/pr/* && 122 git config --add remote.origin.fetch refs/heads/*:refs/remotes/origin/* && 123 124 git fetch --prune origin && 125 git rev-parse origin/main && 126 git rev-parse origin/pr/42 127' 128 129test_expect_success 'fetch --prune --tags prunes branches but not tags' ' 130 cd "$D" && 131 git clone . prune-tags && 132 cd prune-tags && 133 git tag sometag main && 134 # Create what looks like a remote-tracking branch from an earlier 135 # fetch that has since been deleted from the remote: 136 git update-ref refs/remotes/origin/fake-remote main && 137 138 git fetch --prune --tags origin && 139 git rev-parse origin/main && 140 test_must_fail git rev-parse origin/fake-remote && 141 git rev-parse sometag 142' 143 144test_expect_success 'fetch --prune --tags with branch does not prune other things' ' 145 cd "$D" && 146 git clone . prune-tags-branch && 147 cd prune-tags-branch && 148 git tag sometag main && 149 git update-ref refs/remotes/origin/extrabranch main && 150 151 git fetch --prune --tags origin main && 152 git rev-parse origin/extrabranch && 153 git rev-parse sometag 154' 155 156test_expect_success 'fetch --prune --tags with refspec prunes based on refspec' ' 157 cd "$D" && 158 git clone . prune-tags-refspec && 159 cd prune-tags-refspec && 160 git tag sometag main && 161 git update-ref refs/remotes/origin/foo/otherbranch main && 162 git update-ref refs/remotes/origin/extrabranch main && 163 164 git fetch --prune --tags origin refs/heads/foo/*:refs/remotes/origin/foo/* && 165 test_must_fail git rev-parse refs/remotes/origin/foo/otherbranch && 166 git rev-parse origin/extrabranch && 167 git rev-parse sometag 168' 169 170test_expect_success 'fetch --atomic works with a single branch' ' 171 test_when_finished "rm -rf \"$D\"/atomic" && 172 173 cd "$D" && 174 git clone . atomic && 175 git branch atomic-branch && 176 oid=$(git rev-parse atomic-branch) && 177 echo "$oid" >expected && 178 179 git -C atomic fetch --atomic origin && 180 git -C atomic rev-parse origin/atomic-branch >actual && 181 test_cmp expected actual && 182 test $oid = "$(git -C atomic rev-parse --verify FETCH_HEAD)" 183' 184 185test_expect_success 'fetch --atomic works with multiple branches' ' 186 test_when_finished "rm -rf \"$D\"/atomic" && 187 188 cd "$D" && 189 git clone . atomic && 190 git branch atomic-branch-1 && 191 git branch atomic-branch-2 && 192 git branch atomic-branch-3 && 193 git rev-parse refs/heads/atomic-branch-1 refs/heads/atomic-branch-2 refs/heads/atomic-branch-3 >actual && 194 195 git -C atomic fetch --atomic origin && 196 git -C atomic rev-parse refs/remotes/origin/atomic-branch-1 refs/remotes/origin/atomic-branch-2 refs/remotes/origin/atomic-branch-3 >expected && 197 test_cmp expected actual 198' 199 200test_expect_success 'fetch --atomic works with mixed branches and tags' ' 201 test_when_finished "rm -rf \"$D\"/atomic" && 202 203 cd "$D" && 204 git clone . atomic && 205 git branch atomic-mixed-branch && 206 git tag atomic-mixed-tag && 207 git rev-parse refs/heads/atomic-mixed-branch refs/tags/atomic-mixed-tag >actual && 208 209 git -C atomic fetch --tags --atomic origin && 210 git -C atomic rev-parse refs/remotes/origin/atomic-mixed-branch refs/tags/atomic-mixed-tag >expected && 211 test_cmp expected actual 212' 213 214test_expect_success 'fetch --atomic prunes references' ' 215 test_when_finished "rm -rf \"$D\"/atomic" && 216 217 cd "$D" && 218 git branch atomic-prune-delete && 219 git clone . atomic && 220 git branch --delete atomic-prune-delete && 221 git branch atomic-prune-create && 222 git rev-parse refs/heads/atomic-prune-create >actual && 223 224 git -C atomic fetch --prune --atomic origin && 225 test_must_fail git -C atomic rev-parse refs/remotes/origin/atomic-prune-delete && 226 git -C atomic rev-parse refs/remotes/origin/atomic-prune-create >expected && 227 test_cmp expected actual 228' 229 230test_expect_success 'fetch --atomic aborts with non-fast-forward update' ' 231 test_when_finished "rm -rf \"$D\"/atomic" && 232 233 cd "$D" && 234 git branch atomic-non-ff && 235 git clone . atomic && 236 git rev-parse HEAD >actual && 237 238 git branch atomic-new-branch && 239 parent_commit=$(git rev-parse atomic-non-ff~) && 240 git update-ref refs/heads/atomic-non-ff $parent_commit && 241 242 test_must_fail git -C atomic fetch --atomic origin refs/heads/*:refs/remotes/origin/* && 243 test_must_fail git -C atomic rev-parse refs/remotes/origin/atomic-new-branch && 244 git -C atomic rev-parse refs/remotes/origin/atomic-non-ff >expected && 245 test_cmp expected actual && 246 test_must_be_empty atomic/.git/FETCH_HEAD 247' 248 249test_expect_success 'fetch --atomic executes a single reference transaction only' ' 250 test_when_finished "rm -rf \"$D\"/atomic" && 251 252 cd "$D" && 253 git clone . atomic && 254 git branch atomic-hooks-1 && 255 git branch atomic-hooks-2 && 256 head_oid=$(git rev-parse HEAD) && 257 258 cat >expected <<-EOF && 259 prepared 260 $ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-1 261 $ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-2 262 committed 263 $ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-1 264 $ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-2 265 EOF 266 267 rm -f atomic/actual && 268 write_script atomic/.git/hooks/reference-transaction <<-\EOF && 269 ( echo "$*" && cat ) >>actual 270 EOF 271 272 git -C atomic fetch --atomic origin && 273 test_cmp expected atomic/actual 274' 275 276test_expect_success 'fetch --atomic aborts all reference updates if hook aborts' ' 277 test_when_finished "rm -rf \"$D\"/atomic" && 278 279 cd "$D" && 280 git clone . atomic && 281 git branch atomic-hooks-abort-1 && 282 git branch atomic-hooks-abort-2 && 283 git branch atomic-hooks-abort-3 && 284 git tag atomic-hooks-abort && 285 head_oid=$(git rev-parse HEAD) && 286 287 cat >expected <<-EOF && 288 prepared 289 $ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-abort-1 290 $ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-abort-2 291 $ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-abort-3 292 $ZERO_OID $head_oid refs/tags/atomic-hooks-abort 293 aborted 294 $ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-abort-1 295 $ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-abort-2 296 $ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-abort-3 297 $ZERO_OID $head_oid refs/tags/atomic-hooks-abort 298 EOF 299 300 rm -f atomic/actual && 301 write_script atomic/.git/hooks/reference-transaction <<-\EOF && 302 ( echo "$*" && cat ) >>actual 303 exit 1 304 EOF 305 306 git -C atomic for-each-ref >expected-refs && 307 test_must_fail git -C atomic fetch --tags --atomic origin && 308 git -C atomic for-each-ref >actual-refs && 309 test_cmp expected-refs actual-refs && 310 test_must_be_empty atomic/.git/FETCH_HEAD 311' 312 313test_expect_success 'fetch --atomic --append appends to FETCH_HEAD' ' 314 test_when_finished "rm -rf \"$D\"/atomic" && 315 316 cd "$D" && 317 git clone . atomic && 318 oid=$(git rev-parse HEAD) && 319 320 git branch atomic-fetch-head-1 && 321 git -C atomic fetch --atomic origin atomic-fetch-head-1 && 322 test_line_count = 1 atomic/.git/FETCH_HEAD && 323 324 git branch atomic-fetch-head-2 && 325 git -C atomic fetch --atomic --append origin atomic-fetch-head-2 && 326 test_line_count = 2 atomic/.git/FETCH_HEAD && 327 cp atomic/.git/FETCH_HEAD expected && 328 329 write_script atomic/.git/hooks/reference-transaction <<-\EOF && 330 exit 1 331 EOF 332 333 git branch atomic-fetch-head-3 && 334 test_must_fail git -C atomic fetch --atomic --append origin atomic-fetch-head-3 && 335 test_cmp expected atomic/.git/FETCH_HEAD 336' 337 338test_expect_success '--refmap="" ignores configured refspec' ' 339 cd "$TRASH_DIRECTORY" && 340 git clone "$D" remote-refs && 341 git -C remote-refs rev-parse remotes/origin/main >old && 342 git -C remote-refs update-ref refs/remotes/origin/main main~1 && 343 git -C remote-refs rev-parse remotes/origin/main >new && 344 git -C remote-refs fetch --refmap= origin "+refs/heads/*:refs/hidden/origin/*" && 345 git -C remote-refs rev-parse remotes/origin/main >actual && 346 test_cmp new actual && 347 git -C remote-refs fetch origin && 348 git -C remote-refs rev-parse remotes/origin/main >actual && 349 test_cmp old actual 350' 351 352test_expect_success '--refmap="" and --prune' ' 353 git -C remote-refs update-ref refs/remotes/origin/foo/otherbranch main && 354 git -C remote-refs update-ref refs/hidden/foo/otherbranch main && 355 git -C remote-refs fetch --prune --refmap="" origin +refs/heads/*:refs/hidden/* && 356 git -C remote-refs rev-parse remotes/origin/foo/otherbranch && 357 test_must_fail git -C remote-refs rev-parse refs/hidden/foo/otherbranch && 358 git -C remote-refs fetch --prune origin && 359 test_must_fail git -C remote-refs rev-parse remotes/origin/foo/otherbranch 360' 361 362test_expect_success 'fetch tags when there is no tags' ' 363 364 cd "$D" && 365 366 mkdir notags && 367 cd notags && 368 git init && 369 370 git fetch -t .. 371 372' 373 374test_expect_success 'fetch following tags' ' 375 376 cd "$D" && 377 git tag -a -m "annotated" anno HEAD && 378 git tag light HEAD && 379 380 mkdir four && 381 cd four && 382 git init && 383 384 git fetch .. :track && 385 git show-ref --verify refs/tags/anno && 386 git show-ref --verify refs/tags/light 387 388' 389 390test_expect_success 'fetch uses remote ref names to describe new refs' ' 391 cd "$D" && 392 git init descriptive && 393 ( 394 cd descriptive && 395 git config remote.o.url .. && 396 git config remote.o.fetch "refs/heads/*:refs/crazyheads/*" && 397 git config --add remote.o.fetch "refs/others/*:refs/heads/*" && 398 git fetch o 399 ) && 400 git tag -a -m "Descriptive tag" descriptive-tag && 401 git branch descriptive-branch && 402 git checkout descriptive-branch && 403 echo "Nuts" >crazy && 404 git add crazy && 405 git commit -a -m "descriptive commit" && 406 git update-ref refs/others/crazy HEAD && 407 ( 408 cd descriptive && 409 git fetch o 2>actual && 410 test_i18ngrep "new branch.* -> refs/crazyheads/descriptive-branch$" actual && 411 test_i18ngrep "new tag.* -> descriptive-tag$" actual && 412 test_i18ngrep "new ref.* -> crazy$" actual 413 ) && 414 git checkout main 415' 416 417test_expect_success 'fetch must not resolve short tag name' ' 418 419 cd "$D" && 420 421 mkdir five && 422 cd five && 423 git init && 424 425 test_must_fail git fetch .. anno:five 426 427' 428 429test_expect_success 'fetch can now resolve short remote name' ' 430 431 cd "$D" && 432 git update-ref refs/remotes/six/HEAD HEAD && 433 434 mkdir six && 435 cd six && 436 git init && 437 438 git fetch .. six:six 439' 440 441test_expect_success 'create bundle 1' ' 442 cd "$D" && 443 echo >file updated again by origin && 444 git commit -a -m "tip" && 445 git bundle create --version=3 bundle1 main^..main 446' 447 448test_expect_success 'header of bundle looks right' ' 449 cat >expect <<-EOF && 450 # v3 git bundle 451 @object-format=$(test_oid algo) 452 -OID updated by origin 453 OID refs/heads/main 454 455 EOF 456 sed -e "s/$OID_REGEX/OID/g" -e "5q" "$D"/bundle1 >actual && 457 test_cmp expect actual 458' 459 460test_expect_success 'create bundle 2' ' 461 cd "$D" && 462 git bundle create bundle2 main~2..main 463' 464 465test_expect_success 'unbundle 1' ' 466 cd "$D/bundle" && 467 git checkout -b some-branch && 468 test_must_fail git fetch "$D/bundle1" main:main 469' 470 471 472test_expect_success 'bundle 1 has only 3 files ' ' 473 cd "$D" && 474 test_bundle_object_count bundle1 3 475' 476 477test_expect_success 'unbundle 2' ' 478 cd "$D/bundle" && 479 git fetch ../bundle2 main:main && 480 test "tip" = "$(git log -1 --pretty=oneline main | cut -d" " -f2)" 481' 482 483test_expect_success 'bundle does not prerequisite objects' ' 484 cd "$D" && 485 touch file2 && 486 git add file2 && 487 git commit -m add.file2 file2 && 488 git bundle create bundle3 -1 HEAD && 489 test_bundle_object_count bundle3 3 490' 491 492test_expect_success 'bundle should be able to create a full history' ' 493 494 cd "$D" && 495 git tag -a -m "1.0" v1.0 main && 496 git bundle create bundle4 v1.0 497 498' 499 500test_expect_success 'fetch with a non-applying branch.<name>.merge' ' 501 git config branch.main.remote yeti && 502 git config branch.main.merge refs/heads/bigfoot && 503 git config remote.blub.url one && 504 git config remote.blub.fetch "refs/heads/*:refs/remotes/one/*" && 505 git fetch blub 506' 507 508# URL supplied to fetch does not match the url of the configured branch's remote 509test_expect_success 'fetch from GIT URL with a non-applying branch.<name>.merge [1]' ' 510 one_head=$(cd one && git rev-parse HEAD) && 511 this_head=$(git rev-parse HEAD) && 512 git update-ref -d FETCH_HEAD && 513 git fetch one && 514 test $one_head = "$(git rev-parse --verify FETCH_HEAD)" && 515 test $this_head = "$(git rev-parse --verify HEAD)" 516' 517 518# URL supplied to fetch matches the url of the configured branch's remote and 519# the merge spec matches the branch the remote HEAD points to 520test_expect_success 'fetch from GIT URL with a non-applying branch.<name>.merge [2]' ' 521 one_ref=$(cd one && git symbolic-ref HEAD) && 522 git config branch.main.remote blub && 523 git config branch.main.merge "$one_ref" && 524 git update-ref -d FETCH_HEAD && 525 git fetch one && 526 test $one_head = "$(git rev-parse --verify FETCH_HEAD)" && 527 test $this_head = "$(git rev-parse --verify HEAD)" 528' 529 530# URL supplied to fetch matches the url of the configured branch's remote, but 531# the merge spec does not match the branch the remote HEAD points to 532test_expect_success 'fetch from GIT URL with a non-applying branch.<name>.merge [3]' ' 533 git config branch.main.merge "${one_ref}_not" && 534 git update-ref -d FETCH_HEAD && 535 git fetch one && 536 test $one_head = "$(git rev-parse --verify FETCH_HEAD)" && 537 test $this_head = "$(git rev-parse --verify HEAD)" 538' 539 540# the strange name is: a\!'b 541test_expect_success 'quoting of a strangely named repo' ' 542 test_must_fail git fetch "a\\!'\''b" > result 2>&1 && 543 grep "fatal: '\''a\\\\!'\''b'\''" result 544' 545 546test_expect_success 'bundle should record HEAD correctly' ' 547 548 cd "$D" && 549 git bundle create bundle5 HEAD main && 550 git bundle list-heads bundle5 >actual && 551 for h in HEAD refs/heads/main 552 do 553 echo "$(git rev-parse --verify $h) $h" 554 done >expect && 555 test_cmp expect actual 556 557' 558 559test_expect_success 'mark initial state of origin/main' ' 560 ( 561 cd three && 562 git tag base-origin-main refs/remotes/origin/main 563 ) 564' 565 566test_expect_success 'explicit fetch should update tracking' ' 567 568 cd "$D" && 569 git branch -f side && 570 ( 571 cd three && 572 git update-ref refs/remotes/origin/main base-origin-main && 573 o=$(git rev-parse --verify refs/remotes/origin/main) && 574 git fetch origin main && 575 n=$(git rev-parse --verify refs/remotes/origin/main) && 576 test "$o" != "$n" && 577 test_must_fail git rev-parse --verify refs/remotes/origin/side 578 ) 579' 580 581test_expect_success 'explicit pull should update tracking' ' 582 583 cd "$D" && 584 git branch -f side && 585 ( 586 cd three && 587 git update-ref refs/remotes/origin/main base-origin-main && 588 o=$(git rev-parse --verify refs/remotes/origin/main) && 589 git pull origin main && 590 n=$(git rev-parse --verify refs/remotes/origin/main) && 591 test "$o" != "$n" && 592 test_must_fail git rev-parse --verify refs/remotes/origin/side 593 ) 594' 595 596test_expect_success 'explicit --refmap is allowed only with command-line refspec' ' 597 cd "$D" && 598 ( 599 cd three && 600 test_must_fail git fetch --refmap="*:refs/remotes/none/*" 601 ) 602' 603 604test_expect_success 'explicit --refmap option overrides remote.*.fetch' ' 605 cd "$D" && 606 git branch -f side && 607 ( 608 cd three && 609 git update-ref refs/remotes/origin/main base-origin-main && 610 o=$(git rev-parse --verify refs/remotes/origin/main) && 611 git fetch --refmap="refs/heads/*:refs/remotes/other/*" origin main && 612 n=$(git rev-parse --verify refs/remotes/origin/main) && 613 test "$o" = "$n" && 614 test_must_fail git rev-parse --verify refs/remotes/origin/side && 615 git rev-parse --verify refs/remotes/other/main 616 ) 617' 618 619test_expect_success 'explicitly empty --refmap option disables remote.*.fetch' ' 620 cd "$D" && 621 git branch -f side && 622 ( 623 cd three && 624 git update-ref refs/remotes/origin/main base-origin-main && 625 o=$(git rev-parse --verify refs/remotes/origin/main) && 626 git fetch --refmap="" origin main && 627 n=$(git rev-parse --verify refs/remotes/origin/main) && 628 test "$o" = "$n" && 629 test_must_fail git rev-parse --verify refs/remotes/origin/side 630 ) 631' 632 633test_expect_success 'configured fetch updates tracking' ' 634 635 cd "$D" && 636 git branch -f side && 637 ( 638 cd three && 639 git update-ref refs/remotes/origin/main base-origin-main && 640 o=$(git rev-parse --verify refs/remotes/origin/main) && 641 git fetch origin && 642 n=$(git rev-parse --verify refs/remotes/origin/main) && 643 test "$o" != "$n" && 644 git rev-parse --verify refs/remotes/origin/side 645 ) 646' 647 648test_expect_success 'non-matching refspecs do not confuse tracking update' ' 649 cd "$D" && 650 git update-ref refs/odd/location HEAD && 651 ( 652 cd three && 653 git update-ref refs/remotes/origin/main base-origin-main && 654 git config --add remote.origin.fetch \ 655 refs/odd/location:refs/remotes/origin/odd && 656 o=$(git rev-parse --verify refs/remotes/origin/main) && 657 git fetch origin main && 658 n=$(git rev-parse --verify refs/remotes/origin/main) && 659 test "$o" != "$n" && 660 test_must_fail git rev-parse --verify refs/remotes/origin/odd 661 ) 662' 663 664test_expect_success 'pushing nonexistent branch by mistake should not segv' ' 665 666 cd "$D" && 667 test_must_fail git push seven no:no 668 669' 670 671test_expect_success 'auto tag following fetches minimum' ' 672 673 cd "$D" && 674 git clone .git follow && 675 git checkout HEAD^0 && 676 ( 677 for i in 1 2 3 4 5 6 7 678 do 679 echo $i >>file && 680 git commit -m $i -a && 681 git tag -a -m $i excess-$i || exit 1 682 done 683 ) && 684 git checkout main && 685 ( 686 cd follow && 687 git fetch 688 ) 689' 690 691test_expect_success 'refuse to fetch into the current branch' ' 692 693 test_must_fail git fetch . side:main 694 695' 696 697test_expect_success 'fetch into the current branch with --update-head-ok' ' 698 699 git fetch --update-head-ok . side:main 700 701' 702 703test_expect_success 'fetch --dry-run does not touch FETCH_HEAD, but still prints what would be written' ' 704 rm -f .git/FETCH_HEAD err && 705 git fetch --dry-run . 2>err && 706 ! test -f .git/FETCH_HEAD && 707 grep FETCH_HEAD err 708' 709 710test_expect_success '--no-write-fetch-head does not touch FETCH_HEAD, and does not print what would be written' ' 711 rm -f .git/FETCH_HEAD err && 712 git fetch --no-write-fetch-head . 2>err && 713 ! test -f .git/FETCH_HEAD && 714 ! grep FETCH_HEAD err 715' 716 717test_expect_success '--write-fetch-head gets defeated by --dry-run' ' 718 rm -f .git/FETCH_HEAD && 719 git fetch --dry-run --write-fetch-head . && 720 ! test -f .git/FETCH_HEAD 721' 722 723test_expect_success "should be able to fetch with duplicate refspecs" ' 724 mkdir dups && 725 ( 726 cd dups && 727 git init && 728 git config branch.main.remote three && 729 git config remote.three.url ../three/.git && 730 git config remote.three.fetch +refs/heads/*:refs/remotes/origin/* && 731 git config --add remote.three.fetch +refs/heads/*:refs/remotes/origin/* && 732 git fetch three 733 ) 734' 735 736test_expect_success 'LHS of refspec follows ref disambiguation rules' ' 737 mkdir lhs-ambiguous && 738 ( 739 cd lhs-ambiguous && 740 git init server && 741 test_commit -C server unwanted && 742 test_commit -C server wanted && 743 744 git init client && 745 746 # Check a name coming after "refs" alphabetically ... 747 git -C server update-ref refs/heads/s wanted && 748 git -C server update-ref refs/heads/refs/heads/s unwanted && 749 git -C client fetch ../server +refs/heads/s:refs/heads/checkthis && 750 git -C server rev-parse wanted >expect && 751 git -C client rev-parse checkthis >actual && 752 test_cmp expect actual && 753 754 # ... and one before. 755 git -C server update-ref refs/heads/q wanted && 756 git -C server update-ref refs/heads/refs/heads/q unwanted && 757 git -C client fetch ../server +refs/heads/q:refs/heads/checkthis && 758 git -C server rev-parse wanted >expect && 759 git -C client rev-parse checkthis >actual && 760 test_cmp expect actual && 761 762 # Tags are preferred over branches like refs/{heads,tags}/* 763 git -C server update-ref refs/tags/t wanted && 764 git -C server update-ref refs/heads/t unwanted && 765 git -C client fetch ../server +t:refs/heads/checkthis && 766 git -C server rev-parse wanted >expect && 767 git -C client rev-parse checkthis >actual 768 ) 769' 770 771test_expect_success 'fetch.writeCommitGraph' ' 772 git clone three write && 773 ( 774 cd three && 775 test_commit new 776 ) && 777 ( 778 cd write && 779 git -c fetch.writeCommitGraph fetch origin && 780 test_path_is_file .git/objects/info/commit-graphs/commit-graph-chain 781 ) 782' 783 784test_expect_success 'fetch.writeCommitGraph with submodules' ' 785 git clone dups super && 786 ( 787 cd super && 788 git submodule add "file://$TRASH_DIRECTORY/three" && 789 git commit -m "add submodule" 790 ) && 791 git clone "super" super-clone && 792 ( 793 cd super-clone && 794 rm -rf .git/objects/info && 795 git -c fetch.writeCommitGraph=true fetch origin && 796 test_path_is_file .git/objects/info/commit-graphs/commit-graph-chain 797 ) 798' 799 800# configured prune tests 801 802set_config_tristate () { 803 # var=$1 val=$2 804 case "$2" in 805 unset) 806 test_unconfig "$1" 807 ;; 808 *) 809 git config "$1" "$2" 810 key=$(echo $1 | sed -e 's/^remote\.origin/fetch/') 811 git_fetch_c="$git_fetch_c -c $key=$2" 812 ;; 813 esac 814} 815 816test_configured_prune () { 817 test_configured_prune_type "$@" "name" 818 test_configured_prune_type "$@" "link" 819} 820 821test_configured_prune_type () { 822 fetch_prune=$1 823 remote_origin_prune=$2 824 fetch_prune_tags=$3 825 remote_origin_prune_tags=$4 826 expected_branch=$5 827 expected_tag=$6 828 cmdline=$7 829 mode=$8 830 831 if test -z "$cmdline_setup" 832 then 833 test_expect_success 'setup cmdline_setup variable for subsequent test' ' 834 remote_url="file://$(git -C one config remote.origin.url)" && 835 remote_fetch="$(git -C one config remote.origin.fetch)" && 836 cmdline_setup="\"$remote_url\" \"$remote_fetch\"" 837 ' 838 fi 839 840 if test "$mode" = 'link' 841 then 842 new_cmdline="" 843 844 if test "$cmdline" = "" 845 then 846 new_cmdline=$cmdline_setup 847 else 848 new_cmdline=$(printf "%s" "$cmdline" | perl -pe 's[origin(?!/)]["'"$remote_url"'"]g') 849 fi 850 851 if test "$fetch_prune_tags" = 'true' || 852 test "$remote_origin_prune_tags" = 'true' 853 then 854 if ! printf '%s' "$cmdline\n" | grep -q refs/remotes/origin/ 855 then 856 new_cmdline="$new_cmdline refs/tags/*:refs/tags/*" 857 fi 858 fi 859 860 cmdline="$new_cmdline" 861 fi 862 863 test_expect_success "$mode prune fetch.prune=$1 remote.origin.prune=$2 fetch.pruneTags=$3 remote.origin.pruneTags=$4${7:+ $7}; branch:$5 tag:$6" ' 864 # make sure a newbranch is there in . and also in one 865 git branch -f newbranch && 866 git tag -f newtag && 867 ( 868 cd one && 869 test_unconfig fetch.prune && 870 test_unconfig fetch.pruneTags && 871 test_unconfig remote.origin.prune && 872 test_unconfig remote.origin.pruneTags && 873 git fetch '"$cmdline_setup"' && 874 git rev-parse --verify refs/remotes/origin/newbranch && 875 git rev-parse --verify refs/tags/newtag 876 ) && 877 878 # now remove them 879 git branch -d newbranch && 880 git tag -d newtag && 881 882 # then test 883 ( 884 cd one && 885 git_fetch_c="" && 886 set_config_tristate fetch.prune $fetch_prune && 887 set_config_tristate fetch.pruneTags $fetch_prune_tags && 888 set_config_tristate remote.origin.prune $remote_origin_prune && 889 set_config_tristate remote.origin.pruneTags $remote_origin_prune_tags && 890 891 if test "$mode" != "link" 892 then 893 git_fetch_c="" 894 fi && 895 git$git_fetch_c fetch '"$cmdline"' && 896 case "$expected_branch" in 897 pruned) 898 test_must_fail git rev-parse --verify refs/remotes/origin/newbranch 899 ;; 900 kept) 901 git rev-parse --verify refs/remotes/origin/newbranch 902 ;; 903 esac && 904 case "$expected_tag" in 905 pruned) 906 test_must_fail git rev-parse --verify refs/tags/newtag 907 ;; 908 kept) 909 git rev-parse --verify refs/tags/newtag 910 ;; 911 esac 912 ) 913 ' 914} 915 916# $1 config: fetch.prune 917# $2 config: remote.<name>.prune 918# $3 config: fetch.pruneTags 919# $4 config: remote.<name>.pruneTags 920# $5 expect: branch to be pruned? 921# $6 expect: tag to be pruned? 922# $7 git-fetch $cmdline: 923# 924# $1 $2 $3 $4 $5 $6 $7 925test_configured_prune unset unset unset unset kept kept "" 926test_configured_prune unset unset unset unset kept kept "--no-prune" 927test_configured_prune unset unset unset unset pruned kept "--prune" 928test_configured_prune unset unset unset unset kept pruned \ 929 "--prune origin refs/tags/*:refs/tags/*" 930test_configured_prune unset unset unset unset pruned pruned \ 931 "--prune origin refs/tags/*:refs/tags/* +refs/heads/*:refs/remotes/origin/*" 932 933test_configured_prune false unset unset unset kept kept "" 934test_configured_prune false unset unset unset kept kept "--no-prune" 935test_configured_prune false unset unset unset pruned kept "--prune" 936 937test_configured_prune true unset unset unset pruned kept "" 938test_configured_prune true unset unset unset pruned kept "--prune" 939test_configured_prune true unset unset unset kept kept "--no-prune" 940 941test_configured_prune unset false unset unset kept kept "" 942test_configured_prune unset false unset unset kept kept "--no-prune" 943test_configured_prune unset false unset unset pruned kept "--prune" 944 945test_configured_prune false false unset unset kept kept "" 946test_configured_prune false false unset unset kept kept "--no-prune" 947test_configured_prune false false unset unset pruned kept "--prune" 948test_configured_prune false false unset unset kept pruned \ 949 "--prune origin refs/tags/*:refs/tags/*" 950test_configured_prune false false unset unset pruned pruned \ 951 "--prune origin refs/tags/*:refs/tags/* +refs/heads/*:refs/remotes/origin/*" 952 953test_configured_prune true false unset unset kept kept "" 954test_configured_prune true false unset unset pruned kept "--prune" 955test_configured_prune true false unset unset kept kept "--no-prune" 956 957test_configured_prune unset true unset unset pruned kept "" 958test_configured_prune unset true unset unset kept kept "--no-prune" 959test_configured_prune unset true unset unset pruned kept "--prune" 960 961test_configured_prune false true unset unset pruned kept "" 962test_configured_prune false true unset unset kept kept "--no-prune" 963test_configured_prune false true unset unset pruned kept "--prune" 964 965test_configured_prune true true unset unset pruned kept "" 966test_configured_prune true true unset unset pruned kept "--prune" 967test_configured_prune true true unset unset kept kept "--no-prune" 968test_configured_prune true true unset unset kept pruned \ 969 "--prune origin refs/tags/*:refs/tags/*" 970test_configured_prune true true unset unset pruned pruned \ 971 "--prune origin refs/tags/*:refs/tags/* +refs/heads/*:refs/remotes/origin/*" 972 973# --prune-tags on its own does nothing, needs --prune as well, same 974# for fetch.pruneTags without fetch.prune 975test_configured_prune unset unset unset unset kept kept "--prune-tags" 976test_configured_prune unset unset true unset kept kept "" 977test_configured_prune unset unset unset true kept kept "" 978 979# These will prune the tags 980test_configured_prune unset unset unset unset pruned pruned "--prune --prune-tags" 981test_configured_prune true unset true unset pruned pruned "" 982test_configured_prune unset true unset true pruned pruned "" 983 984# remote.<name>.pruneTags overrides fetch.pruneTags, just like 985# remote.<name>.prune overrides fetch.prune if set. 986test_configured_prune true unset true unset pruned pruned "" 987test_configured_prune false true false true pruned pruned "" 988test_configured_prune true false true false kept kept "" 989 990# When --prune-tags is supplied it's ignored if an explicit refspec is 991# given, same for the configuration options. 992test_configured_prune unset unset unset unset pruned kept \ 993 "--prune --prune-tags origin +refs/heads/*:refs/remotes/origin/*" 994test_configured_prune unset unset true unset pruned kept \ 995 "--prune origin +refs/heads/*:refs/remotes/origin/*" 996test_configured_prune unset unset unset true pruned kept \ 997 "--prune origin +refs/heads/*:refs/remotes/origin/*" 998 999# Pruning that also takes place if a file:// url replaces a named 1000# remote. However, because there's no implicit 1001# +refs/heads/*:refs/remotes/origin/* refspec and supplying it on the 1002# command-line negates --prune-tags, the branches will not be pruned. 1003test_configured_prune_type unset unset unset unset kept kept "origin --prune-tags" "name" 1004test_configured_prune_type unset unset unset unset kept kept "origin --prune-tags" "link" 1005test_configured_prune_type unset unset unset unset pruned pruned "origin --prune --prune-tags" "name" 1006test_configured_prune_type unset unset unset unset kept pruned "origin --prune --prune-tags" "link" 1007test_configured_prune_type unset unset unset unset pruned pruned "--prune --prune-tags origin" "name" 1008test_configured_prune_type unset unset unset unset kept pruned "--prune --prune-tags origin" "link" 1009test_configured_prune_type unset unset true unset pruned pruned "--prune origin" "name" 1010test_configured_prune_type unset unset true unset kept pruned "--prune origin" "link" 1011test_configured_prune_type unset unset unset true pruned pruned "--prune origin" "name" 1012test_configured_prune_type unset unset unset true kept pruned "--prune origin" "link" 1013test_configured_prune_type true unset true unset pruned pruned "origin" "name" 1014test_configured_prune_type true unset true unset kept pruned "origin" "link" 1015test_configured_prune_type unset true true unset pruned pruned "origin" "name" 1016test_configured_prune_type unset true true unset kept pruned "origin" "link" 1017test_configured_prune_type unset true unset true pruned pruned "origin" "name" 1018test_configured_prune_type unset true unset true kept pruned "origin" "link" 1019 1020# When all remote.origin.fetch settings are deleted a --prune 1021# --prune-tags still implicitly supplies refs/tags/*:refs/tags/* so 1022# tags, but not tracking branches, will be deleted. 1023test_expect_success 'remove remote.origin.fetch "one"' ' 1024 ( 1025 cd one && 1026 git config --unset-all remote.origin.fetch 1027 ) 1028' 1029test_configured_prune_type unset unset unset unset kept pruned "origin --prune --prune-tags" "name" 1030test_configured_prune_type unset unset unset unset kept pruned "origin --prune --prune-tags" "link" 1031 1032test_expect_success 'all boundary commits are excluded' ' 1033 test_commit base && 1034 test_commit oneside && 1035 git checkout HEAD^ && 1036 test_commit otherside && 1037 git checkout main && 1038 test_tick && 1039 git merge otherside && 1040 ad=$(git log --no-walk --format=%ad HEAD) && 1041 git bundle create twoside-boundary.bdl main --since="$ad" && 1042 test_bundle_object_count --thin twoside-boundary.bdl 3 1043' 1044 1045test_expect_success 'fetch --prune prints the remotes url' ' 1046 git branch goodbye && 1047 git clone . only-prunes && 1048 git branch -D goodbye && 1049 ( 1050 cd only-prunes && 1051 git fetch --prune origin 2>&1 | head -n1 >../actual 1052 ) && 1053 echo "From ${D}/." >expect && 1054 test_cmp expect actual 1055' 1056 1057test_expect_success 'branchname D/F conflict resolved by --prune' ' 1058 git branch dir/file && 1059 git clone . prune-df-conflict && 1060 git branch -D dir/file && 1061 git branch dir && 1062 ( 1063 cd prune-df-conflict && 1064 git fetch --prune && 1065 git rev-parse origin/dir >../actual 1066 ) && 1067 git rev-parse dir >expect && 1068 test_cmp expect actual 1069' 1070 1071test_expect_success 'fetching a one-level ref works' ' 1072 test_commit extra && 1073 git reset --hard HEAD^ && 1074 git update-ref refs/foo extra && 1075 git init one-level && 1076 ( 1077 cd one-level && 1078 git fetch .. HEAD refs/foo 1079 ) 1080' 1081 1082test_expect_success 'fetching with auto-gc does not lock up' ' 1083 write_script askyesno <<-\EOF && 1084 echo "$*" && 1085 false 1086 EOF 1087 git clone "file://$D" auto-gc && 1088 test_commit test2 && 1089 ( 1090 cd auto-gc && 1091 git config fetch.unpackLimit 1 && 1092 git config gc.autoPackLimit 1 && 1093 git config gc.autoDetach false && 1094 GIT_ASK_YESNO="$D/askyesno" git fetch --verbose >fetch.out 2>&1 && 1095 test_i18ngrep "Auto packing the repository" fetch.out && 1096 ! grep "Should I try again" fetch.out 1097 ) 1098' 1099 1100test_expect_success 'fetch aligned output' ' 1101 git clone . full-output && 1102 test_commit looooooooooooong-tag && 1103 ( 1104 cd full-output && 1105 git -c fetch.output=full fetch origin >actual 2>&1 && 1106 grep -e "->" actual | cut -c 22- >../actual 1107 ) && 1108 cat >expect <<-\EOF && 1109 main -> origin/main 1110 looooooooooooong-tag -> looooooooooooong-tag 1111 EOF 1112 test_cmp expect actual 1113' 1114 1115test_expect_success 'fetch compact output' ' 1116 git clone . compact && 1117 test_commit extraaa && 1118 ( 1119 cd compact && 1120 git -c fetch.output=compact fetch origin >actual 2>&1 && 1121 grep -e "->" actual | cut -c 22- >../actual 1122 ) && 1123 cat >expect <<-\EOF && 1124 main -> origin/* 1125 extraaa -> * 1126 EOF 1127 test_cmp expect actual 1128' 1129 1130test_expect_success '--no-show-forced-updates' ' 1131 mkdir forced-updates && 1132 ( 1133 cd forced-updates && 1134 git init && 1135 test_commit 1 && 1136 test_commit 2 1137 ) && 1138 git clone forced-updates forced-update-clone && 1139 git clone forced-updates no-forced-update-clone && 1140 git -C forced-updates reset --hard HEAD~1 && 1141 ( 1142 cd forced-update-clone && 1143 git fetch --show-forced-updates origin 2>output && 1144 test_i18ngrep "(forced update)" output 1145 ) && 1146 ( 1147 cd no-forced-update-clone && 1148 git fetch --no-show-forced-updates origin 2>output && 1149 test_i18ngrep ! "(forced update)" output 1150 ) 1151' 1152 1153setup_negotiation_tip () { 1154 SERVER="$1" 1155 URL="$2" 1156 USE_PROTOCOL_V2="$3" 1157 1158 rm -rf "$SERVER" client trace && 1159 git init -b main "$SERVER" && 1160 test_commit -C "$SERVER" alpha_1 && 1161 test_commit -C "$SERVER" alpha_2 && 1162 git -C "$SERVER" checkout --orphan beta && 1163 test_commit -C "$SERVER" beta_1 && 1164 test_commit -C "$SERVER" beta_2 && 1165 1166 git clone "$URL" client && 1167 1168 if test "$USE_PROTOCOL_V2" -eq 1 1169 then 1170 git -C "$SERVER" config protocol.version 2 && 1171 git -C client config protocol.version 2 1172 fi && 1173 1174 test_commit -C "$SERVER" beta_s && 1175 git -C "$SERVER" checkout main && 1176 test_commit -C "$SERVER" alpha_s && 1177 git -C "$SERVER" tag -d alpha_1 alpha_2 beta_1 beta_2 1178} 1179 1180check_negotiation_tip () { 1181 # Ensure that {alpha,beta}_1 are sent as "have", but not {alpha_beta}_2 1182 ALPHA_1=$(git -C client rev-parse alpha_1) && 1183 grep "fetch> have $ALPHA_1" trace && 1184 BETA_1=$(git -C client rev-parse beta_1) && 1185 grep "fetch> have $BETA_1" trace && 1186 ALPHA_2=$(git -C client rev-parse alpha_2) && 1187 ! grep "fetch> have $ALPHA_2" trace && 1188 BETA_2=$(git -C client rev-parse beta_2) && 1189 ! grep "fetch> have $BETA_2" trace 1190} 1191 1192test_expect_success '--negotiation-tip limits "have" lines sent' ' 1193 setup_negotiation_tip server server 0 && 1194 GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch \ 1195 --negotiation-tip=alpha_1 --negotiation-tip=beta_1 \ 1196 origin alpha_s beta_s && 1197 check_negotiation_tip 1198' 1199 1200test_expect_success '--negotiation-tip understands globs' ' 1201 setup_negotiation_tip server server 0 && 1202 GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch \ 1203 --negotiation-tip=*_1 \ 1204 origin alpha_s beta_s && 1205 check_negotiation_tip 1206' 1207 1208test_expect_success '--negotiation-tip understands abbreviated SHA-1' ' 1209 setup_negotiation_tip server server 0 && 1210 GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch \ 1211 --negotiation-tip=$(git -C client rev-parse --short alpha_1) \ 1212 --negotiation-tip=$(git -C client rev-parse --short beta_1) \ 1213 origin alpha_s beta_s && 1214 check_negotiation_tip 1215' 1216 1217test_expect_success '--negotiation-tip rejects missing OIDs' ' 1218 setup_negotiation_tip server server 0 && 1219 test_must_fail git -C client fetch \ 1220 --negotiation-tip=alpha_1 \ 1221 --negotiation-tip=$(test_oid zero) \ 1222 origin alpha_s beta_s 2>err && 1223 cat >fatal-expect <<-EOF && 1224 fatal: the object $(test_oid zero) does not exist 1225EOF 1226 grep fatal: err >fatal-actual && 1227 test_cmp fatal-expect fatal-actual 1228' 1229 1230. "$TEST_DIRECTORY"/lib-httpd.sh 1231start_httpd 1232 1233test_expect_success '--negotiation-tip limits "have" lines sent with HTTP protocol v2' ' 1234 setup_negotiation_tip "$HTTPD_DOCUMENT_ROOT_PATH/server" \ 1235 "$HTTPD_URL/smart/server" 1 && 1236 GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch \ 1237 --negotiation-tip=alpha_1 --negotiation-tip=beta_1 \ 1238 origin alpha_s beta_s && 1239 check_negotiation_tip 1240' 1241 1242# DO NOT add non-httpd-specific tests here, because the last part of this 1243# test script is only executed when httpd is available and enabled. 1244 1245test_done 1246