string-list.[ch]: add a string_list_init_{nodup,dup}()
[git.git] / t / t2400-worktree-add.sh
blob96dfca1554217df3a9ed734f7dff21e04659dbef
1 #!/bin/sh
3 test_description='test git worktree add'
5 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
6 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
8 . ./test-lib.sh
10 . "$TEST_DIRECTORY"/lib-rebase.sh
12 test_expect_success 'setup' '
13 test_commit init
16 test_expect_success '"add" an existing worktree' '
17 mkdir -p existing/subtree &&
18 test_must_fail git worktree add --detach existing main
21 test_expect_success '"add" an existing empty worktree' '
22 mkdir existing_empty &&
23 git worktree add --detach existing_empty main
26 test_expect_success '"add" using shorthand - fails when no previous branch' '
27 test_must_fail git worktree add existing_short -
30 test_expect_success '"add" using - shorthand' '
31 git checkout -b newbranch &&
32 echo hello >myworld &&
33 git add myworld &&
34 git commit -m myworld &&
35 git checkout main &&
36 git worktree add short-hand - &&
37 echo refs/heads/newbranch >expect &&
38 git -C short-hand rev-parse --symbolic-full-name HEAD >actual &&
39 test_cmp expect actual
42 test_expect_success '"add" refuses to checkout locked branch' '
43 test_must_fail git worktree add zere main &&
44 ! test -d zere &&
45 ! test -d .git/worktrees/zere
48 test_expect_success 'checking out paths not complaining about linked checkouts' '
50 cd existing_empty &&
51 echo dirty >>init.t &&
52 git checkout main -- init.t
56 test_expect_success '"add" worktree' '
57 git rev-parse HEAD >expect &&
58 git worktree add --detach here main &&
60 cd here &&
61 test_cmp ../init.t init.t &&
62 test_must_fail git symbolic-ref HEAD &&
63 git rev-parse HEAD >actual &&
64 test_cmp ../expect actual &&
65 git fsck
69 test_expect_success '"add" worktree with lock' '
70 git rev-parse HEAD >expect &&
71 git worktree add --detach --lock here-with-lock main &&
72 test -f .git/worktrees/here-with-lock/locked
75 test_expect_success '"add" worktree from a subdir' '
77 mkdir sub &&
78 cd sub &&
79 git worktree add --detach here main &&
80 cd here &&
81 test_cmp ../../init.t init.t
85 test_expect_success '"add" from a linked checkout' '
87 cd here &&
88 git worktree add --detach nested-here main &&
89 cd nested-here &&
90 git fsck
94 test_expect_success '"add" worktree creating new branch' '
95 git worktree add -b newmain there main &&
97 cd there &&
98 test_cmp ../init.t init.t &&
99 git symbolic-ref HEAD >actual &&
100 echo refs/heads/newmain >expect &&
101 test_cmp expect actual &&
102 git fsck
106 test_expect_success 'die the same branch is already checked out' '
108 cd here &&
109 test_must_fail git checkout newmain
113 test_expect_success SYMLINKS 'die the same branch is already checked out (symlink)' '
114 head=$(git -C there rev-parse --git-path HEAD) &&
115 ref=$(git -C there symbolic-ref HEAD) &&
116 rm "$head" &&
117 ln -s "$ref" "$head" &&
118 test_must_fail git -C here checkout newmain
121 test_expect_success 'not die the same branch is already checked out' '
123 cd here &&
124 git worktree add --force anothernewmain newmain
128 test_expect_success 'not die on re-checking out current branch' '
130 cd there &&
131 git checkout newmain
135 test_expect_success '"add" from a bare repo' '
137 git clone --bare . bare &&
138 cd bare &&
139 git worktree add -b bare-main ../there2 main
143 test_expect_success 'checkout from a bare repo without "add"' '
145 cd bare &&
146 test_must_fail git checkout main
150 test_expect_success '"add" default branch of a bare repo' '
152 git clone --bare . bare2 &&
153 cd bare2 &&
154 git worktree add ../there3 main
158 test_expect_success 'checkout with grafts' '
159 test_when_finished rm .git/info/grafts &&
160 test_commit abc &&
161 SHA1=$(git rev-parse HEAD) &&
162 test_commit def &&
163 test_commit xyz &&
164 echo "$(git rev-parse HEAD) $SHA1" >.git/info/grafts &&
165 cat >expected <<-\EOF &&
169 git log --format=%s -2 >actual &&
170 test_cmp expected actual &&
171 git worktree add --detach grafted main &&
172 git --git-dir=grafted/.git log --format=%s -2 >actual &&
173 test_cmp expected actual
176 test_expect_success '"add" from relative HEAD' '
177 test_commit a &&
178 test_commit b &&
179 test_commit c &&
180 git rev-parse HEAD~1 >expected &&
181 git worktree add relhead HEAD~1 &&
182 git -C relhead rev-parse HEAD >actual &&
183 test_cmp expected actual
186 test_expect_success '"add -b" with <branch> omitted' '
187 git worktree add -b burble flornk &&
188 test_cmp_rev HEAD burble
191 test_expect_success '"add --detach" with <branch> omitted' '
192 git worktree add --detach fishhook &&
193 git rev-parse HEAD >expected &&
194 git -C fishhook rev-parse HEAD >actual &&
195 test_cmp expected actual &&
196 test_must_fail git -C fishhook symbolic-ref HEAD
199 test_expect_success '"add" with <branch> omitted' '
200 git worktree add wiffle/bat &&
201 test_cmp_rev HEAD bat
204 test_expect_success '"add" checks out existing branch of dwimd name' '
205 git branch dwim HEAD~1 &&
206 git worktree add dwim &&
207 test_cmp_rev HEAD~1 dwim &&
209 cd dwim &&
210 test_cmp_rev HEAD dwim
214 test_expect_success '"add <path>" dwim fails with checked out branch' '
215 git checkout -b test-branch &&
216 test_must_fail git worktree add test-branch &&
217 test_path_is_missing test-branch
220 test_expect_success '"add --force" with existing dwimd name doesnt die' '
221 git checkout test-branch &&
222 git worktree add --force test-branch
225 test_expect_success '"add" no auto-vivify with --detach and <branch> omitted' '
226 git worktree add --detach mish/mash &&
227 test_must_fail git rev-parse mash -- &&
228 test_must_fail git -C mish/mash symbolic-ref HEAD
231 test_expect_success '"add" -b/-B mutually exclusive' '
232 test_must_fail git worktree add -b poodle -B poodle bamboo main
235 test_expect_success '"add" -b/--detach mutually exclusive' '
236 test_must_fail git worktree add -b poodle --detach bamboo main
239 test_expect_success '"add" -B/--detach mutually exclusive' '
240 test_must_fail git worktree add -B poodle --detach bamboo main
243 test_expect_success '"add -B" fails if the branch is checked out' '
244 git rev-parse newmain >before &&
245 test_must_fail git worktree add -B newmain bamboo main &&
246 git rev-parse newmain >after &&
247 test_cmp before after
250 test_expect_success 'add -B' '
251 git worktree add -B poodle bamboo2 main^ &&
252 git -C bamboo2 symbolic-ref HEAD >actual &&
253 echo refs/heads/poodle >expected &&
254 test_cmp expected actual &&
255 test_cmp_rev main^ poodle
258 test_expect_success 'add --quiet' '
259 git worktree add --quiet another-worktree main 2>actual &&
260 test_must_be_empty actual
263 test_expect_success 'local clone from linked checkout' '
264 git clone --local here here-clone &&
265 ( cd here-clone && git fsck )
268 test_expect_success 'local clone --shared from linked checkout' '
269 git -C bare worktree add --detach ../baretree &&
270 git clone --local --shared baretree bare-clone &&
271 grep /bare/ bare-clone/.git/objects/info/alternates
274 test_expect_success '"add" worktree with --no-checkout' '
275 git worktree add --no-checkout -b swamp swamp &&
276 ! test -e swamp/init.t &&
277 git -C swamp reset --hard &&
278 test_cmp init.t swamp/init.t
281 test_expect_success '"add" worktree with --checkout' '
282 git worktree add --checkout -b swmap2 swamp2 &&
283 test_cmp init.t swamp2/init.t
286 test_expect_success 'put a worktree under rebase' '
287 git worktree add under-rebase &&
289 cd under-rebase &&
290 set_fake_editor &&
291 FAKE_LINES="edit 1" git rebase -i HEAD^ &&
292 git worktree list | grep "under-rebase.*detached HEAD"
296 test_expect_success 'add a worktree, checking out a rebased branch' '
297 test_must_fail git worktree add new-rebase under-rebase &&
298 ! test -d new-rebase
301 test_expect_success 'checking out a rebased branch from another worktree' '
302 git worktree add new-place &&
303 test_must_fail git -C new-place checkout under-rebase
306 test_expect_success 'not allow to delete a branch under rebase' '
308 cd under-rebase &&
309 test_must_fail git branch -D under-rebase
313 test_expect_success 'rename a branch under rebase not allowed' '
314 test_must_fail git branch -M under-rebase rebase-with-new-name
317 test_expect_success 'check out from current worktree branch ok' '
319 cd under-rebase &&
320 git checkout under-rebase &&
321 git checkout - &&
322 git rebase --abort
326 test_expect_success 'checkout a branch under bisect' '
327 git worktree add under-bisect &&
329 cd under-bisect &&
330 git bisect start &&
331 git bisect bad &&
332 git bisect good HEAD~2 &&
333 git worktree list | grep "under-bisect.*detached HEAD" &&
334 test_must_fail git worktree add new-bisect under-bisect &&
335 ! test -d new-bisect
339 test_expect_success 'rename a branch under bisect not allowed' '
340 test_must_fail git branch -M under-bisect bisect-with-new-name
342 # Is branch "refs/heads/$1" set to pull from "$2/$3"?
343 test_branch_upstream () {
344 printf "%s\n" "$2" "refs/heads/$3" >expect.upstream &&
346 git config "branch.$1.remote" &&
347 git config "branch.$1.merge"
348 } >actual.upstream &&
349 test_cmp expect.upstream actual.upstream
352 test_expect_success '--track sets up tracking' '
353 test_when_finished rm -rf track &&
354 git worktree add --track -b track track main &&
355 test_branch_upstream track . main
358 # setup remote repository $1 and repository $2 with $1 set up as
359 # remote. The remote has two branches, main and foo.
360 setup_remote_repo () {
361 git init $1 &&
363 cd $1 &&
364 test_commit $1_main &&
365 git checkout -b foo &&
366 test_commit upstream_foo
367 ) &&
368 git init $2 &&
370 cd $2 &&
371 test_commit $2_main &&
372 git remote add $1 ../$1 &&
373 git config remote.$1.fetch \
374 "refs/heads/*:refs/remotes/$1/*" &&
375 git fetch --all
379 test_expect_success '--no-track avoids setting up tracking' '
380 test_when_finished rm -rf repo_upstream repo_local foo &&
381 setup_remote_repo repo_upstream repo_local &&
383 cd repo_local &&
384 git worktree add --no-track -b foo ../foo repo_upstream/foo
385 ) &&
387 cd foo &&
388 test_must_fail git config "branch.foo.remote" &&
389 test_must_fail git config "branch.foo.merge" &&
390 test_cmp_rev refs/remotes/repo_upstream/foo refs/heads/foo
394 test_expect_success '"add" <path> <non-existent-branch> fails' '
395 test_must_fail git worktree add foo non-existent
398 test_expect_success '"add" <path> <branch> dwims' '
399 test_when_finished rm -rf repo_upstream repo_dwim foo &&
400 setup_remote_repo repo_upstream repo_dwim &&
401 git init repo_dwim &&
403 cd repo_dwim &&
404 git worktree add ../foo foo
405 ) &&
407 cd foo &&
408 test_branch_upstream foo repo_upstream foo &&
409 test_cmp_rev refs/remotes/repo_upstream/foo refs/heads/foo
413 test_expect_success '"add" <path> <branch> dwims with checkout.defaultRemote' '
414 test_when_finished rm -rf repo_upstream repo_dwim foo &&
415 setup_remote_repo repo_upstream repo_dwim &&
416 git init repo_dwim &&
418 cd repo_dwim &&
419 git remote add repo_upstream2 ../repo_upstream &&
420 git fetch repo_upstream2 &&
421 test_must_fail git worktree add ../foo foo &&
422 git -c checkout.defaultRemote=repo_upstream worktree add ../foo foo &&
423 git status -uno --porcelain >status.actual &&
424 test_must_be_empty status.actual
425 ) &&
427 cd foo &&
428 test_branch_upstream foo repo_upstream foo &&
429 test_cmp_rev refs/remotes/repo_upstream/foo refs/heads/foo
433 test_expect_success 'git worktree add does not match remote' '
434 test_when_finished rm -rf repo_a repo_b foo &&
435 setup_remote_repo repo_a repo_b &&
437 cd repo_b &&
438 git worktree add ../foo
439 ) &&
441 cd foo &&
442 test_must_fail git config "branch.foo.remote" &&
443 test_must_fail git config "branch.foo.merge" &&
444 test_cmp_rev ! refs/remotes/repo_a/foo refs/heads/foo
448 test_expect_success 'git worktree add --guess-remote sets up tracking' '
449 test_when_finished rm -rf repo_a repo_b foo &&
450 setup_remote_repo repo_a repo_b &&
452 cd repo_b &&
453 git worktree add --guess-remote ../foo
454 ) &&
456 cd foo &&
457 test_branch_upstream foo repo_a foo &&
458 test_cmp_rev refs/remotes/repo_a/foo refs/heads/foo
462 test_expect_success 'git worktree add with worktree.guessRemote sets up tracking' '
463 test_when_finished rm -rf repo_a repo_b foo &&
464 setup_remote_repo repo_a repo_b &&
466 cd repo_b &&
467 git config worktree.guessRemote true &&
468 git worktree add ../foo
469 ) &&
471 cd foo &&
472 test_branch_upstream foo repo_a foo &&
473 test_cmp_rev refs/remotes/repo_a/foo refs/heads/foo
477 test_expect_success 'git worktree --no-guess-remote option overrides config' '
478 test_when_finished rm -rf repo_a repo_b foo &&
479 setup_remote_repo repo_a repo_b &&
481 cd repo_b &&
482 git config worktree.guessRemote true &&
483 git worktree add --no-guess-remote ../foo
484 ) &&
486 cd foo &&
487 test_must_fail git config "branch.foo.remote" &&
488 test_must_fail git config "branch.foo.merge" &&
489 test_cmp_rev ! refs/remotes/repo_a/foo refs/heads/foo
493 post_checkout_hook () {
494 gitdir=${1:-.git}
495 test_when_finished "rm -f $gitdir/hooks/post-checkout" &&
496 mkdir -p $gitdir/hooks &&
497 write_script $gitdir/hooks/post-checkout <<-\EOF
499 echo $*
500 git rev-parse --git-dir --show-toplevel
501 } >hook.actual
505 test_expect_success '"add" invokes post-checkout hook (branch)' '
506 post_checkout_hook &&
508 echo $ZERO_OID $(git rev-parse HEAD) 1 &&
509 echo $(pwd)/.git/worktrees/gumby &&
510 echo $(pwd)/gumby
511 } >hook.expect &&
512 git worktree add gumby &&
513 test_cmp hook.expect gumby/hook.actual
516 test_expect_success '"add" invokes post-checkout hook (detached)' '
517 post_checkout_hook &&
519 echo $ZERO_OID $(git rev-parse HEAD) 1 &&
520 echo $(pwd)/.git/worktrees/grumpy &&
521 echo $(pwd)/grumpy
522 } >hook.expect &&
523 git worktree add --detach grumpy &&
524 test_cmp hook.expect grumpy/hook.actual
527 test_expect_success '"add --no-checkout" suppresses post-checkout hook' '
528 post_checkout_hook &&
529 rm -f hook.actual &&
530 git worktree add --no-checkout gloopy &&
531 test_path_is_missing gloopy/hook.actual
534 test_expect_success '"add" in other worktree invokes post-checkout hook' '
535 post_checkout_hook &&
537 echo $ZERO_OID $(git rev-parse HEAD) 1 &&
538 echo $(pwd)/.git/worktrees/guppy &&
539 echo $(pwd)/guppy
540 } >hook.expect &&
541 git -C gloopy worktree add --detach ../guppy &&
542 test_cmp hook.expect guppy/hook.actual
545 test_expect_success '"add" in bare repo invokes post-checkout hook' '
546 rm -rf bare &&
547 git clone --bare . bare &&
549 echo $ZERO_OID $(git --git-dir=bare rev-parse HEAD) 1 &&
550 echo $(pwd)/bare/worktrees/goozy &&
551 echo $(pwd)/goozy
552 } >hook.expect &&
553 post_checkout_hook bare &&
554 git -C bare worktree add --detach ../goozy &&
555 test_cmp hook.expect goozy/hook.actual
558 test_expect_success '"add" an existing but missing worktree' '
559 git worktree add --detach pneu &&
560 test_must_fail git worktree add --detach pneu &&
561 rm -fr pneu &&
562 test_must_fail git worktree add --detach pneu &&
563 git worktree add --force --detach pneu
566 test_expect_success '"add" an existing locked but missing worktree' '
567 git worktree add --detach gnoo &&
568 git worktree lock gnoo &&
569 test_when_finished "git worktree unlock gnoo || :" &&
570 rm -fr gnoo &&
571 test_must_fail git worktree add --detach gnoo &&
572 test_must_fail git worktree add --force --detach gnoo &&
573 git worktree add --force --force --detach gnoo
576 test_expect_success '"add" not tripped up by magic worktree matching"' '
577 # if worktree "sub1/bar" exists, "git worktree add bar" in distinct
578 # directory `sub2` should not mistakenly complain that `bar` is an
579 # already-registered worktree
580 mkdir sub1 sub2 &&
581 git -C sub1 --git-dir=../.git worktree add --detach bozo &&
582 git -C sub2 --git-dir=../.git worktree add --detach bozo
585 test_expect_success FUNNYNAMES 'sanitize generated worktree name' '
586 git worktree add --detach ". weird*..?.lock.lock" &&
587 test -d .git/worktrees/---weird-.-
590 test_expect_success '"add" should not fail because of another bad worktree' '
591 git init add-fail &&
593 cd add-fail &&
594 test_commit first &&
595 mkdir sub &&
596 git worktree add sub/to-be-deleted &&
597 rm -rf sub &&
598 git worktree add second
602 test_expect_success '"add" with uninitialized submodule, with submodule.recurse unset' '
603 test_create_repo submodule &&
604 test_commit -C submodule first &&
605 test_create_repo project &&
606 git -C project submodule add ../submodule &&
607 git -C project add submodule &&
608 test_tick &&
609 git -C project commit -m add_sub &&
610 git clone project project-clone &&
611 git -C project-clone worktree add ../project-2
613 test_expect_success '"add" with uninitialized submodule, with submodule.recurse set' '
614 git -C project-clone -c submodule.recurse worktree add ../project-3
617 test_expect_success '"add" with initialized submodule, with submodule.recurse unset' '
618 git -C project-clone submodule update --init &&
619 git -C project-clone worktree add ../project-4
622 test_expect_success '"add" with initialized submodule, with submodule.recurse set' '
623 git -C project-clone -c submodule.recurse worktree add ../project-5
626 test_done