]>
Commit | Line | Data |
---|---|---|
529fef20 NTND |
1 | #!/bin/sh |
2 | ||
f194b1ef | 3 | test_description='test git worktree add' |
529fef20 NTND |
4 | |
5 | . ./test-lib.sh | |
6 | ||
8d9fdd70 NTND |
7 | . "$TEST_DIRECTORY"/lib-rebase.sh |
8 | ||
529fef20 NTND |
9 | test_expect_success 'setup' ' |
10 | test_commit init | |
11 | ' | |
12 | ||
f194b1ef | 13 | test_expect_success '"add" an existing worktree' ' |
ee4fb843 | 14 | mkdir -p existing/subtree && |
f194b1ef | 15 | test_must_fail git worktree add --detach existing master |
529fef20 NTND |
16 | ' |
17 | ||
f194b1ef | 18 | test_expect_success '"add" an existing empty worktree' ' |
ee4fb843 | 19 | mkdir existing_empty && |
f194b1ef | 20 | git worktree add --detach existing_empty master |
ee4fb843 MK |
21 | ' |
22 | ||
1a450e2f JDG |
23 | test_expect_success '"add" using shorthand - fails when no previous branch' ' |
24 | test_must_fail git worktree add existing_short - | |
25 | ' | |
26 | ||
27 | test_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 | ||
f194b1ef ES |
39 | test_expect_success '"add" refuses to checkout locked branch' ' |
40 | test_must_fail git worktree add zere master && | |
3b8925c7 NTND |
41 | ! test -d zere && |
42 | ! test -d .git/worktrees/zere | |
43 | ' | |
44 | ||
e1c1ab9d NTND |
45 | test_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 | ||
f194b1ef | 53 | test_expect_success '"add" worktree' ' |
5883034c | 54 | git rev-parse HEAD >expect && |
f194b1ef | 55 | git worktree add --detach here master && |
529fef20 NTND |
56 | ( |
57 | cd here && | |
58 | test_cmp ../init.t init.t && | |
5883034c NTND |
59 | test_must_fail git symbolic-ref HEAD && |
60 | git rev-parse HEAD >actual && | |
61 | test_cmp ../expect actual && | |
529fef20 NTND |
62 | git fsck |
63 | ) | |
64 | ' | |
65 | ||
507e6e9e NTND |
66 | test_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 | ||
f194b1ef | 72 | test_expect_success '"add" worktree from a subdir' ' |
529fef20 NTND |
73 | ( |
74 | mkdir sub && | |
75 | cd sub && | |
f194b1ef | 76 | git worktree add --detach here master && |
529fef20 NTND |
77 | cd here && |
78 | test_cmp ../../init.t init.t | |
79 | ) | |
80 | ' | |
81 | ||
f194b1ef | 82 | test_expect_success '"add" from a linked checkout' ' |
529fef20 NTND |
83 | ( |
84 | cd here && | |
f194b1ef | 85 | git worktree add --detach nested-here master && |
529fef20 NTND |
86 | cd nested-here && |
87 | git fsck | |
88 | ) | |
89 | ' | |
90 | ||
f194b1ef ES |
91 | test_expect_success '"add" worktree creating new branch' ' |
92 | git worktree add -b newmaster there master && | |
529fef20 NTND |
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 | ||
5883034c NTND |
103 | test_expect_success 'die the same branch is already checked out' ' |
104 | ( | |
105 | cd here && | |
106 | test_must_fail git checkout newmaster | |
107 | ) | |
108 | ' | |
109 | ||
746bbdc6 ES |
110 | test_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 | ||
1d0fa898 NTND |
118 | test_expect_success 'not die the same branch is already checked out' ' |
119 | ( | |
120 | cd here && | |
f194b1ef | 121 | git worktree add --force anothernewmaster newmaster |
1d0fa898 NTND |
122 | ) |
123 | ' | |
124 | ||
5883034c NTND |
125 | test_expect_success 'not die on re-checking out current branch' ' |
126 | ( | |
127 | cd there && | |
128 | git checkout newmaster | |
129 | ) | |
130 | ' | |
131 | ||
f194b1ef | 132 | test_expect_success '"add" from a bare repo' ' |
3473ad0c DK |
133 | ( |
134 | git clone --bare . bare && | |
135 | cd bare && | |
f194b1ef | 136 | git worktree add -b bare-master ../there2 master |
3473ad0c DK |
137 | ) |
138 | ' | |
139 | ||
f194b1ef | 140 | test_expect_success 'checkout from a bare repo without "add"' ' |
3473ad0c DK |
141 | ( |
142 | cd bare && | |
143 | test_must_fail git checkout master | |
144 | ) | |
145 | ' | |
146 | ||
171c646f DK |
147 | test_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 | ||
ad35f615 NTND |
155 | test_expect_success 'checkout with grafts' ' |
156 | test_when_finished rm .git/info/grafts && | |
157 | test_commit abc && | |
697b90d7 | 158 | SHA1=$(git rev-parse HEAD) && |
ad35f615 NTND |
159 | test_commit def && |
160 | test_commit xyz && | |
697b90d7 | 161 | echo "$(git rev-parse HEAD) $SHA1" >.git/info/grafts && |
ad35f615 NTND |
162 | cat >expected <<-\EOF && |
163 | xyz | |
164 | abc | |
165 | EOF | |
166 | git log --format=%s -2 >actual && | |
167 | test_cmp expected actual && | |
f194b1ef | 168 | git worktree add --detach grafted master && |
ad35f615 NTND |
169 | git --git-dir=grafted/.git log --format=%s -2 >actual && |
170 | test_cmp expected actual | |
171 | ' | |
172 | ||
f194b1ef | 173 | test_expect_success '"add" from relative HEAD' ' |
c990a4c1 ES |
174 | test_commit a && |
175 | test_commit b && | |
176 | test_commit c && | |
177 | git rev-parse HEAD~1 >expected && | |
f194b1ef | 178 | git worktree add relhead HEAD~1 && |
c990a4c1 ES |
179 | git -C relhead rev-parse HEAD >actual && |
180 | test_cmp expected actual | |
181 | ' | |
182 | ||
0f4af3b9 ES |
183 | test_expect_success '"add -b" with <branch> omitted' ' |
184 | git worktree add -b burble flornk && | |
185 | test_cmp_rev HEAD burble | |
186 | ' | |
187 | ||
5c942570 ES |
188 | test_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 | ||
1eb07d82 ES |
196 | test_expect_success '"add" with <branch> omitted' ' |
197 | git worktree add wiffle/bat && | |
198 | test_cmp_rev HEAD bat | |
199 | ' | |
200 | ||
f60a7b76 TG |
201 | test_expect_success '"add" checks out existing branch of dwimd name' ' |
202 | git branch dwim HEAD~1 && | |
203 | git worktree add dwim && | |
204 | test_cmp_rev HEAD~1 dwim && | |
205 | ( | |
206 | cd dwim && | |
207 | test_cmp_rev HEAD dwim | |
208 | ) | |
209 | ' | |
210 | ||
211 | test_expect_success '"add <path>" dwim fails with checked out branch' ' | |
212 | git checkout -b test-branch && | |
213 | test_must_fail git worktree add test-branch && | |
214 | test_path_is_missing test-branch | |
215 | ' | |
216 | ||
217 | test_expect_success '"add --force" with existing dwimd name doesnt die' ' | |
218 | git checkout test-branch && | |
219 | git worktree add --force test-branch | |
1eb07d82 ES |
220 | ' |
221 | ||
5c942570 ES |
222 | test_expect_success '"add" no auto-vivify with --detach and <branch> omitted' ' |
223 | git worktree add --detach mish/mash && | |
224 | test_must_fail git rev-parse mash -- && | |
225 | test_must_fail git -C mish/mash symbolic-ref HEAD | |
226 | ' | |
227 | ||
ab0b2c53 ES |
228 | test_expect_success '"add" -b/-B mutually exclusive' ' |
229 | test_must_fail git worktree add -b poodle -B poodle bamboo master | |
230 | ' | |
231 | ||
232 | test_expect_success '"add" -b/--detach mutually exclusive' ' | |
233 | test_must_fail git worktree add -b poodle --detach bamboo master | |
234 | ' | |
235 | ||
236 | test_expect_success '"add" -B/--detach mutually exclusive' ' | |
237 | test_must_fail git worktree add -B poodle --detach bamboo master | |
238 | ' | |
239 | ||
beb6f24b NTND |
240 | test_expect_success '"add -B" fails if the branch is checked out' ' |
241 | git rev-parse newmaster >before && | |
242 | test_must_fail git worktree add -B newmaster bamboo master && | |
243 | git rev-parse newmaster >after && | |
244 | test_cmp before after | |
245 | ' | |
246 | ||
0ebf4a2a NTND |
247 | test_expect_success 'add -B' ' |
248 | git worktree add -B poodle bamboo2 master^ && | |
249 | git -C bamboo2 symbolic-ref HEAD >actual && | |
250 | echo refs/heads/poodle >expected && | |
251 | test_cmp expected actual && | |
252 | test_cmp_rev master^ poodle | |
253 | ' | |
254 | ||
371979c2 EP |
255 | test_expect_success 'add --quiet' ' |
256 | git worktree add --quiet another-worktree master 2>actual && | |
257 | test_must_be_empty actual | |
258 | ' | |
259 | ||
744e4697 NTND |
260 | test_expect_success 'local clone from linked checkout' ' |
261 | git clone --local here here-clone && | |
262 | ( cd here-clone && git fsck ) | |
263 | ' | |
264 | ||
b3b05971 ES |
265 | test_expect_success 'local clone --shared from linked checkout' ' |
266 | git -C bare worktree add --detach ../baretree && | |
267 | git clone --local --shared baretree bare-clone && | |
268 | grep /bare/ bare-clone/.git/objects/info/alternates | |
269 | ' | |
270 | ||
ef2a0ac9 RZ |
271 | test_expect_success '"add" worktree with --no-checkout' ' |
272 | git worktree add --no-checkout -b swamp swamp && | |
273 | ! test -e swamp/init.t && | |
274 | git -C swamp reset --hard && | |
275 | test_cmp init.t swamp/init.t | |
276 | ' | |
277 | ||
278 | test_expect_success '"add" worktree with --checkout' ' | |
279 | git worktree add --checkout -b swmap2 swamp2 && | |
280 | test_cmp init.t swamp2/init.t | |
281 | ' | |
282 | ||
8d9fdd70 NTND |
283 | test_expect_success 'put a worktree under rebase' ' |
284 | git worktree add under-rebase && | |
285 | ( | |
286 | cd under-rebase && | |
287 | set_fake_editor && | |
288 | FAKE_LINES="edit 1" git rebase -i HEAD^ && | |
289 | git worktree list | grep "under-rebase.*detached HEAD" | |
290 | ) | |
291 | ' | |
292 | ||
293 | test_expect_success 'add a worktree, checking out a rebased branch' ' | |
294 | test_must_fail git worktree add new-rebase under-rebase && | |
295 | ! test -d new-rebase | |
296 | ' | |
297 | ||
298 | test_expect_success 'checking out a rebased branch from another worktree' ' | |
299 | git worktree add new-place && | |
300 | test_must_fail git -C new-place checkout under-rebase | |
301 | ' | |
302 | ||
303 | test_expect_success 'not allow to delete a branch under rebase' ' | |
304 | ( | |
305 | cd under-rebase && | |
306 | test_must_fail git branch -D under-rebase | |
307 | ) | |
308 | ' | |
309 | ||
14ace5b7 NTND |
310 | test_expect_success 'rename a branch under rebase not allowed' ' |
311 | test_must_fail git branch -M under-rebase rebase-with-new-name | |
312 | ' | |
313 | ||
8d9fdd70 NTND |
314 | test_expect_success 'check out from current worktree branch ok' ' |
315 | ( | |
316 | cd under-rebase && | |
317 | git checkout under-rebase && | |
318 | git checkout - && | |
319 | git rebase --abort | |
320 | ) | |
321 | ' | |
322 | ||
04a3dfb8 NTND |
323 | test_expect_success 'checkout a branch under bisect' ' |
324 | git worktree add under-bisect && | |
325 | ( | |
326 | cd under-bisect && | |
327 | git bisect start && | |
328 | git bisect bad && | |
329 | git bisect good HEAD~2 && | |
330 | git worktree list | grep "under-bisect.*detached HEAD" && | |
331 | test_must_fail git worktree add new-bisect under-bisect && | |
332 | ! test -d new-bisect | |
333 | ) | |
334 | ' | |
335 | ||
14ace5b7 NTND |
336 | test_expect_success 'rename a branch under bisect not allowed' ' |
337 | test_must_fail git branch -M under-bisect bisect-with-new-name | |
338 | ' | |
e284e892 TG |
339 | # Is branch "refs/heads/$1" set to pull from "$2/$3"? |
340 | test_branch_upstream () { | |
341 | printf "%s\n" "$2" "refs/heads/$3" >expect.upstream && | |
342 | { | |
343 | git config "branch.$1.remote" && | |
344 | git config "branch.$1.merge" | |
345 | } >actual.upstream && | |
346 | test_cmp expect.upstream actual.upstream | |
347 | } | |
348 | ||
349 | test_expect_success '--track sets up tracking' ' | |
350 | test_when_finished rm -rf track && | |
351 | git worktree add --track -b track track master && | |
352 | test_branch_upstream track . master | |
353 | ' | |
354 | ||
355 | # setup remote repository $1 and repository $2 with $1 set up as | |
356 | # remote. The remote has two branches, master and foo. | |
357 | setup_remote_repo () { | |
358 | git init $1 && | |
359 | ( | |
360 | cd $1 && | |
361 | test_commit $1_master && | |
362 | git checkout -b foo && | |
363 | test_commit upstream_foo | |
364 | ) && | |
365 | git init $2 && | |
366 | ( | |
367 | cd $2 && | |
368 | test_commit $2_master && | |
369 | git remote add $1 ../$1 && | |
370 | git config remote.$1.fetch \ | |
371 | "refs/heads/*:refs/remotes/$1/*" && | |
372 | git fetch --all | |
373 | ) | |
374 | } | |
375 | ||
376 | test_expect_success '--no-track avoids setting up tracking' ' | |
377 | test_when_finished rm -rf repo_upstream repo_local foo && | |
378 | setup_remote_repo repo_upstream repo_local && | |
379 | ( | |
380 | cd repo_local && | |
381 | git worktree add --no-track -b foo ../foo repo_upstream/foo | |
382 | ) && | |
383 | ( | |
384 | cd foo && | |
385 | test_must_fail git config "branch.foo.remote" && | |
386 | test_must_fail git config "branch.foo.merge" && | |
387 | test_cmp_rev refs/remotes/repo_upstream/foo refs/heads/foo | |
388 | ) | |
389 | ' | |
14ace5b7 | 390 | |
4e853331 TG |
391 | test_expect_success '"add" <path> <non-existent-branch> fails' ' |
392 | test_must_fail git worktree add foo non-existent | |
393 | ' | |
394 | ||
395 | test_expect_success '"add" <path> <branch> dwims' ' | |
396 | test_when_finished rm -rf repo_upstream repo_dwim foo && | |
397 | setup_remote_repo repo_upstream repo_dwim && | |
398 | git init repo_dwim && | |
399 | ( | |
400 | cd repo_dwim && | |
401 | git worktree add ../foo foo | |
402 | ) && | |
403 | ( | |
404 | cd foo && | |
405 | test_branch_upstream foo repo_upstream foo && | |
406 | test_cmp_rev refs/remotes/repo_upstream/foo refs/heads/foo | |
407 | ) | |
408 | ' | |
409 | ||
8d7b558b ÆAB |
410 | test_expect_success '"add" <path> <branch> dwims with checkout.defaultRemote' ' |
411 | test_when_finished rm -rf repo_upstream repo_dwim foo && | |
412 | setup_remote_repo repo_upstream repo_dwim && | |
413 | git init repo_dwim && | |
414 | ( | |
415 | cd repo_dwim && | |
416 | git remote add repo_upstream2 ../repo_upstream && | |
417 | git fetch repo_upstream2 && | |
418 | test_must_fail git worktree add ../foo foo && | |
419 | git -c checkout.defaultRemote=repo_upstream worktree add ../foo foo && | |
8d7b558b | 420 | git status -uno --porcelain >status.actual && |
9f4bcf81 | 421 | test_must_be_empty status.actual |
8d7b558b ÆAB |
422 | ) && |
423 | ( | |
424 | cd foo && | |
425 | test_branch_upstream foo repo_upstream foo && | |
426 | test_cmp_rev refs/remotes/repo_upstream/foo refs/heads/foo | |
427 | ) | |
428 | ' | |
429 | ||
71d6682d TG |
430 | test_expect_success 'git worktree add does not match remote' ' |
431 | test_when_finished rm -rf repo_a repo_b foo && | |
432 | setup_remote_repo repo_a repo_b && | |
433 | ( | |
434 | cd repo_b && | |
435 | git worktree add ../foo | |
436 | ) && | |
437 | ( | |
438 | cd foo && | |
439 | test_must_fail git config "branch.foo.remote" && | |
440 | test_must_fail git config "branch.foo.merge" && | |
441 | ! test_cmp_rev refs/remotes/repo_a/foo refs/heads/foo | |
442 | ) | |
443 | ' | |
444 | ||
445 | test_expect_success 'git worktree add --guess-remote sets up tracking' ' | |
446 | test_when_finished rm -rf repo_a repo_b foo && | |
447 | setup_remote_repo repo_a repo_b && | |
448 | ( | |
449 | cd repo_b && | |
450 | git worktree add --guess-remote ../foo | |
451 | ) && | |
452 | ( | |
453 | cd foo && | |
454 | test_branch_upstream foo repo_a foo && | |
455 | test_cmp_rev refs/remotes/repo_a/foo refs/heads/foo | |
456 | ) | |
457 | ' | |
458 | ||
e92445a7 TG |
459 | test_expect_success 'git worktree add with worktree.guessRemote sets up tracking' ' |
460 | test_when_finished rm -rf repo_a repo_b foo && | |
461 | setup_remote_repo repo_a repo_b && | |
462 | ( | |
463 | cd repo_b && | |
464 | git config worktree.guessRemote true && | |
465 | git worktree add ../foo | |
466 | ) && | |
467 | ( | |
468 | cd foo && | |
469 | test_branch_upstream foo repo_a foo && | |
470 | test_cmp_rev refs/remotes/repo_a/foo refs/heads/foo | |
471 | ) | |
472 | ' | |
473 | ||
474 | test_expect_success 'git worktree --no-guess-remote option overrides config' ' | |
475 | test_when_finished rm -rf repo_a repo_b foo && | |
476 | setup_remote_repo repo_a repo_b && | |
477 | ( | |
478 | cd repo_b && | |
479 | git config worktree.guessRemote true && | |
480 | git worktree add --no-guess-remote ../foo | |
481 | ) && | |
482 | ( | |
483 | cd foo && | |
484 | test_must_fail git config "branch.foo.remote" && | |
485 | test_must_fail git config "branch.foo.merge" && | |
486 | ! test_cmp_rev refs/remotes/repo_a/foo refs/heads/foo | |
487 | ) | |
488 | ' | |
489 | ||
ade546be | 490 | post_checkout_hook () { |
a4bf1e3c ES |
491 | gitdir=${1:-.git} |
492 | test_when_finished "rm -f $gitdir/hooks/post-checkout" && | |
493 | mkdir -p $gitdir/hooks && | |
494 | write_script $gitdir/hooks/post-checkout <<-\EOF | |
495 | { | |
496 | echo $* | |
497 | git rev-parse --git-dir --show-toplevel | |
498 | } >hook.actual | |
ade546be ES |
499 | EOF |
500 | } | |
501 | ||
502 | test_expect_success '"add" invokes post-checkout hook (branch)' ' | |
503 | post_checkout_hook && | |
a4bf1e3c | 504 | { |
8125a58b | 505 | echo $ZERO_OID $(git rev-parse HEAD) 1 && |
a4bf1e3c ES |
506 | echo $(pwd)/.git/worktrees/gumby && |
507 | echo $(pwd)/gumby | |
508 | } >hook.expect && | |
ade546be | 509 | git worktree add gumby && |
a4bf1e3c | 510 | test_cmp hook.expect gumby/hook.actual |
ade546be ES |
511 | ' |
512 | ||
513 | test_expect_success '"add" invokes post-checkout hook (detached)' ' | |
514 | post_checkout_hook && | |
a4bf1e3c | 515 | { |
8125a58b | 516 | echo $ZERO_OID $(git rev-parse HEAD) 1 && |
a4bf1e3c ES |
517 | echo $(pwd)/.git/worktrees/grumpy && |
518 | echo $(pwd)/grumpy | |
519 | } >hook.expect && | |
ade546be | 520 | git worktree add --detach grumpy && |
a4bf1e3c | 521 | test_cmp hook.expect grumpy/hook.actual |
ade546be ES |
522 | ' |
523 | ||
524 | test_expect_success '"add --no-checkout" suppresses post-checkout hook' ' | |
525 | post_checkout_hook && | |
526 | rm -f hook.actual && | |
527 | git worktree add --no-checkout gloopy && | |
a4bf1e3c ES |
528 | test_path_is_missing gloopy/hook.actual |
529 | ' | |
530 | ||
531 | test_expect_success '"add" in other worktree invokes post-checkout hook' ' | |
532 | post_checkout_hook && | |
533 | { | |
8125a58b | 534 | echo $ZERO_OID $(git rev-parse HEAD) 1 && |
a4bf1e3c ES |
535 | echo $(pwd)/.git/worktrees/guppy && |
536 | echo $(pwd)/guppy | |
537 | } >hook.expect && | |
538 | git -C gloopy worktree add --detach ../guppy && | |
539 | test_cmp hook.expect guppy/hook.actual | |
540 | ' | |
541 | ||
542 | test_expect_success '"add" in bare repo invokes post-checkout hook' ' | |
543 | rm -rf bare && | |
544 | git clone --bare . bare && | |
545 | { | |
8125a58b | 546 | echo $ZERO_OID $(git --git-dir=bare rev-parse HEAD) 1 && |
a4bf1e3c ES |
547 | echo $(pwd)/bare/worktrees/goozy && |
548 | echo $(pwd)/goozy | |
549 | } >hook.expect && | |
550 | post_checkout_hook bare && | |
551 | git -C bare worktree add --detach ../goozy && | |
552 | test_cmp hook.expect goozy/hook.actual | |
ade546be ES |
553 | ' |
554 | ||
529fef20 | 555 | test_done |