d0d2e4f7ec3310ec51da7144fa87151129f393c0
   1#!/bin/sh
   2
   3test_description='test git worktree add'
   4
   5. ./test-lib.sh
   6
   7. "$TEST_DIRECTORY"/lib-rebase.sh
   8
   9test_expect_success 'setup' '
  10        test_commit init
  11'
  12
  13test_expect_success '"add" an existing worktree' '
  14        mkdir -p existing/subtree &&
  15        test_must_fail git worktree add --detach existing master
  16'
  17
  18test_expect_success '"add" an existing empty worktree' '
  19        mkdir existing_empty &&
  20        git worktree add --detach existing_empty master
  21'
  22
  23test_expect_success '"add" using shorthand - fails when no previous branch' '
  24        test_must_fail git worktree add existing_short -
  25'
  26
  27test_expect_success '"add" using - shorthand' '
  28        git checkout -b newbranch &&
  29        echo hello >myworld &&
  30        git add myworld &&
  31        git commit -m myworld &&
  32        git checkout master &&
  33        git worktree add short-hand - &&
  34        echo refs/heads/newbranch >expect &&
  35        git -C short-hand rev-parse --symbolic-full-name HEAD >actual &&
  36        test_cmp expect actual
  37'
  38
  39test_expect_success '"add" refuses to checkout locked branch' '
  40        test_must_fail git worktree add zere master &&
  41        ! test -d zere &&
  42        ! test -d .git/worktrees/zere
  43'
  44
  45test_expect_success 'checking out paths not complaining about linked checkouts' '
  46        (
  47        cd existing_empty &&
  48        echo dirty >>init.t &&
  49        git checkout master -- init.t
  50        )
  51'
  52
  53test_expect_success '"add" worktree' '
  54        git rev-parse HEAD >expect &&
  55        git worktree add --detach here master &&
  56        (
  57                cd here &&
  58                test_cmp ../init.t init.t &&
  59                test_must_fail git symbolic-ref HEAD &&
  60                git rev-parse HEAD >actual &&
  61                test_cmp ../expect actual &&
  62                git fsck
  63        )
  64'
  65
  66test_expect_success '"add" worktree with lock' '
  67        git rev-parse HEAD >expect &&
  68        git worktree add --detach --lock here-with-lock master &&
  69        test -f .git/worktrees/here-with-lock/locked
  70'
  71
  72test_expect_success '"add" worktree from a subdir' '
  73        (
  74                mkdir sub &&
  75                cd sub &&
  76                git worktree add --detach here master &&
  77                cd here &&
  78                test_cmp ../../init.t init.t
  79        )
  80'
  81
  82test_expect_success '"add" from a linked checkout' '
  83        (
  84                cd here &&
  85                git worktree add --detach nested-here master &&
  86                cd nested-here &&
  87                git fsck
  88        )
  89'
  90
  91test_expect_success '"add" worktree creating new branch' '
  92        git worktree add -b newmaster there master &&
  93        (
  94                cd there &&
  95                test_cmp ../init.t init.t &&
  96                git symbolic-ref HEAD >actual &&
  97                echo refs/heads/newmaster >expect &&
  98                test_cmp expect actual &&
  99                git fsck
 100        )
 101'
 102
 103test_expect_success 'die the same branch is already checked out' '
 104        (
 105                cd here &&
 106                test_must_fail git checkout newmaster
 107        )
 108'
 109
 110test_expect_success SYMLINKS 'die the same branch is already checked out (symlink)' '
 111        head=$(git -C there rev-parse --git-path HEAD) &&
 112        ref=$(git -C there symbolic-ref HEAD) &&
 113        rm "$head" &&
 114        ln -s "$ref" "$head" &&
 115        test_must_fail git -C here checkout newmaster
 116'
 117
 118test_expect_success 'not die the same branch is already checked out' '
 119        (
 120                cd here &&
 121                git worktree add --force anothernewmaster newmaster
 122        )
 123'
 124
 125test_expect_success 'not die on re-checking out current branch' '
 126        (
 127                cd there &&
 128                git checkout newmaster
 129        )
 130'
 131
 132test_expect_success '"add" from a bare repo' '
 133        (
 134                git clone --bare . bare &&
 135                cd bare &&
 136                git worktree add -b bare-master ../there2 master
 137        )
 138'
 139
 140test_expect_success 'checkout from a bare repo without "add"' '
 141        (
 142                cd bare &&
 143                test_must_fail git checkout master
 144        )
 145'
 146
 147test_expect_success '"add" default branch of a bare repo' '
 148        (
 149                git clone --bare . bare2 &&
 150                cd bare2 &&
 151                git worktree add ../there3 master
 152        )
 153'
 154
 155test_expect_success 'checkout with grafts' '
 156        test_when_finished rm .git/info/grafts &&
 157        test_commit abc &&
 158        SHA1=$(git rev-parse HEAD) &&
 159        test_commit def &&
 160        test_commit xyz &&
 161        echo "$(git rev-parse HEAD) $SHA1" >.git/info/grafts &&
 162        cat >expected <<-\EOF &&
 163        xyz
 164        abc
 165        EOF
 166        git log --format=%s -2 >actual &&
 167        test_cmp expected actual &&
 168        git worktree add --detach grafted master &&
 169        git --git-dir=grafted/.git log --format=%s -2 >actual &&
 170        test_cmp expected actual
 171'
 172
 173test_expect_success '"add" from relative HEAD' '
 174        test_commit a &&
 175        test_commit b &&
 176        test_commit c &&
 177        git rev-parse HEAD~1 >expected &&
 178        git worktree add relhead HEAD~1 &&
 179        git -C relhead rev-parse HEAD >actual &&
 180        test_cmp expected actual
 181'
 182
 183test_expect_success '"add -b" with <branch> omitted' '
 184        git worktree add -b burble flornk &&
 185        test_cmp_rev HEAD burble
 186'
 187
 188test_expect_success '"add --detach" with <branch> omitted' '
 189        git worktree add --detach fishhook &&
 190        git rev-parse HEAD >expected &&
 191        git -C fishhook rev-parse HEAD >actual &&
 192        test_cmp expected actual &&
 193        test_must_fail git -C fishhook symbolic-ref HEAD
 194'
 195
 196test_expect_success '"add" with <branch> omitted' '
 197        git worktree add wiffle/bat &&
 198        test_cmp_rev HEAD bat
 199'
 200
 201test_expect_success '"add" auto-vivify does not clobber existing branch' '
 202        test_commit c1 &&
 203        test_commit c2 &&
 204        git branch precious HEAD~1 &&
 205        test_must_fail git worktree add precious &&
 206        test_cmp_rev HEAD~1 precious &&
 207        test_path_is_missing precious
 208'
 209
 210test_expect_success '"add" no auto-vivify with --detach and <branch> omitted' '
 211        git worktree add --detach mish/mash &&
 212        test_must_fail git rev-parse mash -- &&
 213        test_must_fail git -C mish/mash symbolic-ref HEAD
 214'
 215
 216test_expect_success '"add" -b/-B mutually exclusive' '
 217        test_must_fail git worktree add -b poodle -B poodle bamboo master
 218'
 219
 220test_expect_success '"add" -b/--detach mutually exclusive' '
 221        test_must_fail git worktree add -b poodle --detach bamboo master
 222'
 223
 224test_expect_success '"add" -B/--detach mutually exclusive' '
 225        test_must_fail git worktree add -B poodle --detach bamboo master
 226'
 227
 228test_expect_success '"add -B" fails if the branch is checked out' '
 229        git rev-parse newmaster >before &&
 230        test_must_fail git worktree add -B newmaster bamboo master &&
 231        git rev-parse newmaster >after &&
 232        test_cmp before after
 233'
 234
 235test_expect_success 'add -B' '
 236        git worktree add -B poodle bamboo2 master^ &&
 237        git -C bamboo2 symbolic-ref HEAD >actual &&
 238        echo refs/heads/poodle >expected &&
 239        test_cmp expected actual &&
 240        test_cmp_rev master^ poodle
 241'
 242
 243test_expect_success 'local clone from linked checkout' '
 244        git clone --local here here-clone &&
 245        ( cd here-clone && git fsck )
 246'
 247
 248test_expect_success 'local clone --shared from linked checkout' '
 249        git -C bare worktree add --detach ../baretree &&
 250        git clone --local --shared baretree bare-clone &&
 251        grep /bare/ bare-clone/.git/objects/info/alternates
 252'
 253
 254test_expect_success '"add" worktree with --no-checkout' '
 255        git worktree add --no-checkout -b swamp swamp &&
 256        ! test -e swamp/init.t &&
 257        git -C swamp reset --hard &&
 258        test_cmp init.t swamp/init.t
 259'
 260
 261test_expect_success '"add" worktree with --checkout' '
 262        git worktree add --checkout -b swmap2 swamp2 &&
 263        test_cmp init.t swamp2/init.t
 264'
 265
 266test_expect_success 'put a worktree under rebase' '
 267        git worktree add under-rebase &&
 268        (
 269                cd under-rebase &&
 270                set_fake_editor &&
 271                FAKE_LINES="edit 1" git rebase -i HEAD^ &&
 272                git worktree list | grep "under-rebase.*detached HEAD"
 273        )
 274'
 275
 276test_expect_success 'add a worktree, checking out a rebased branch' '
 277        test_must_fail git worktree add new-rebase under-rebase &&
 278        ! test -d new-rebase
 279'
 280
 281test_expect_success 'checking out a rebased branch from another worktree' '
 282        git worktree add new-place &&
 283        test_must_fail git -C new-place checkout under-rebase
 284'
 285
 286test_expect_success 'not allow to delete a branch under rebase' '
 287        (
 288                cd under-rebase &&
 289                test_must_fail git branch -D under-rebase
 290        )
 291'
 292
 293test_expect_success 'rename a branch under rebase not allowed' '
 294        test_must_fail git branch -M under-rebase rebase-with-new-name
 295'
 296
 297test_expect_success 'check out from current worktree branch ok' '
 298        (
 299                cd under-rebase &&
 300                git checkout under-rebase &&
 301                git checkout - &&
 302                git rebase --abort
 303        )
 304'
 305
 306test_expect_success 'checkout a branch under bisect' '
 307        git worktree add under-bisect &&
 308        (
 309                cd under-bisect &&
 310                git bisect start &&
 311                git bisect bad &&
 312                git bisect good HEAD~2 &&
 313                git worktree list | grep "under-bisect.*detached HEAD" &&
 314                test_must_fail git worktree add new-bisect under-bisect &&
 315                ! test -d new-bisect
 316        )
 317'
 318
 319test_expect_success 'rename a branch under bisect not allowed' '
 320        test_must_fail git branch -M under-bisect bisect-with-new-name
 321'
 322# Is branch "refs/heads/$1" set to pull from "$2/$3"?
 323test_branch_upstream () {
 324        printf "%s\n" "$2" "refs/heads/$3" >expect.upstream &&
 325        {
 326                git config "branch.$1.remote" &&
 327                git config "branch.$1.merge"
 328        } >actual.upstream &&
 329        test_cmp expect.upstream actual.upstream
 330}
 331
 332test_expect_success '--track sets up tracking' '
 333        test_when_finished rm -rf track &&
 334        git worktree add --track -b track track master &&
 335        test_branch_upstream track . master
 336'
 337
 338# setup remote repository $1 and repository $2 with $1 set up as
 339# remote.  The remote has two branches, master and foo.
 340setup_remote_repo () {
 341        git init $1 &&
 342        (
 343                cd $1 &&
 344                test_commit $1_master &&
 345                git checkout -b foo &&
 346                test_commit upstream_foo
 347        ) &&
 348        git init $2 &&
 349        (
 350                cd $2 &&
 351                test_commit $2_master &&
 352                git remote add $1 ../$1 &&
 353                git config remote.$1.fetch \
 354                        "refs/heads/*:refs/remotes/$1/*" &&
 355                git fetch --all
 356        )
 357}
 358
 359test_expect_success '--no-track avoids setting up tracking' '
 360        test_when_finished rm -rf repo_upstream repo_local foo &&
 361        setup_remote_repo repo_upstream repo_local &&
 362        (
 363                cd repo_local &&
 364                git worktree add --no-track -b foo ../foo repo_upstream/foo
 365        ) &&
 366        (
 367                cd foo &&
 368                test_must_fail git config "branch.foo.remote" &&
 369                test_must_fail git config "branch.foo.merge" &&
 370                test_cmp_rev refs/remotes/repo_upstream/foo refs/heads/foo
 371        )
 372'
 373
 374test_expect_success '"add" <path> <non-existent-branch> fails' '
 375        test_must_fail git worktree add foo non-existent
 376'
 377
 378test_expect_success '"add" <path> <branch> dwims' '
 379        test_when_finished rm -rf repo_upstream repo_dwim foo &&
 380        setup_remote_repo repo_upstream repo_dwim &&
 381        git init repo_dwim &&
 382        (
 383                cd repo_dwim &&
 384                git worktree add ../foo foo
 385        ) &&
 386        (
 387                cd foo &&
 388                test_branch_upstream foo repo_upstream foo &&
 389                test_cmp_rev refs/remotes/repo_upstream/foo refs/heads/foo
 390        )
 391'
 392
 393test_expect_success 'git worktree add does not match remote' '
 394        test_when_finished rm -rf repo_a repo_b foo &&
 395        setup_remote_repo repo_a repo_b &&
 396        (
 397                cd repo_b &&
 398                git worktree add ../foo
 399        ) &&
 400        (
 401                cd foo &&
 402                test_must_fail git config "branch.foo.remote" &&
 403                test_must_fail git config "branch.foo.merge" &&
 404                ! test_cmp_rev refs/remotes/repo_a/foo refs/heads/foo
 405        )
 406'
 407
 408test_expect_success 'git worktree add --guess-remote sets up tracking' '
 409        test_when_finished rm -rf repo_a repo_b foo &&
 410        setup_remote_repo repo_a repo_b &&
 411        (
 412                cd repo_b &&
 413                git worktree add --guess-remote ../foo
 414        ) &&
 415        (
 416                cd foo &&
 417                test_branch_upstream foo repo_a foo &&
 418                test_cmp_rev refs/remotes/repo_a/foo refs/heads/foo
 419        )
 420'
 421
 422test_expect_success 'git worktree add with worktree.guessRemote sets up tracking' '
 423        test_when_finished rm -rf repo_a repo_b foo &&
 424        setup_remote_repo repo_a repo_b &&
 425        (
 426                cd repo_b &&
 427                git config worktree.guessRemote true &&
 428                git worktree add ../foo
 429        ) &&
 430        (
 431                cd foo &&
 432                test_branch_upstream foo repo_a foo &&
 433                test_cmp_rev refs/remotes/repo_a/foo refs/heads/foo
 434        )
 435'
 436
 437test_expect_success 'git worktree --no-guess-remote option overrides config' '
 438        test_when_finished rm -rf repo_a repo_b foo &&
 439        setup_remote_repo repo_a repo_b &&
 440        (
 441                cd repo_b &&
 442                git config worktree.guessRemote true &&
 443                git worktree add --no-guess-remote ../foo
 444        ) &&
 445        (
 446                cd foo &&
 447                test_must_fail git config "branch.foo.remote" &&
 448                test_must_fail git config "branch.foo.merge" &&
 449                ! test_cmp_rev refs/remotes/repo_a/foo refs/heads/foo
 450        )
 451'
 452
 453post_checkout_hook () {
 454        gitdir=${1:-.git}
 455        test_when_finished "rm -f $gitdir/hooks/post-checkout" &&
 456        mkdir -p $gitdir/hooks &&
 457        write_script $gitdir/hooks/post-checkout <<-\EOF
 458        {
 459                echo $*
 460                git rev-parse --git-dir --show-toplevel
 461        } >hook.actual
 462        EOF
 463}
 464
 465test_expect_success '"add" invokes post-checkout hook (branch)' '
 466        post_checkout_hook &&
 467        {
 468                echo $_z40 $(git rev-parse HEAD) 1 &&
 469                echo $(pwd)/.git/worktrees/gumby &&
 470                echo $(pwd)/gumby
 471        } >hook.expect &&
 472        git worktree add gumby &&
 473        test_cmp hook.expect gumby/hook.actual
 474'
 475
 476test_expect_success '"add" invokes post-checkout hook (detached)' '
 477        post_checkout_hook &&
 478        {
 479                echo $_z40 $(git rev-parse HEAD) 1 &&
 480                echo $(pwd)/.git/worktrees/grumpy &&
 481                echo $(pwd)/grumpy
 482        } >hook.expect &&
 483        git worktree add --detach grumpy &&
 484        test_cmp hook.expect grumpy/hook.actual
 485'
 486
 487test_expect_success '"add --no-checkout" suppresses post-checkout hook' '
 488        post_checkout_hook &&
 489        rm -f hook.actual &&
 490        git worktree add --no-checkout gloopy &&
 491        test_path_is_missing gloopy/hook.actual
 492'
 493
 494test_expect_success '"add" in other worktree invokes post-checkout hook' '
 495        post_checkout_hook &&
 496        {
 497                echo $_z40 $(git rev-parse HEAD) 1 &&
 498                echo $(pwd)/.git/worktrees/guppy &&
 499                echo $(pwd)/guppy
 500        } >hook.expect &&
 501        git -C gloopy worktree add --detach ../guppy &&
 502        test_cmp hook.expect guppy/hook.actual
 503'
 504
 505test_expect_success '"add" in bare repo invokes post-checkout hook' '
 506        rm -rf bare &&
 507        git clone --bare . bare &&
 508        {
 509                echo $_z40 $(git --git-dir=bare rev-parse HEAD) 1 &&
 510                echo $(pwd)/bare/worktrees/goozy &&
 511                echo $(pwd)/goozy
 512        } >hook.expect &&
 513        post_checkout_hook bare &&
 514        git -C bare worktree add --detach ../goozy &&
 515        test_cmp hook.expect goozy/hook.actual
 516'
 517
 518test_done