Raw
1 #!/bin/sh
2 # Copyright (c) 2006, Junio C Hamano.
3
4 test_description='Per branch config variables affects "git fetch".
5
6 '
7
8 . ./test-lib.sh
9 . "$TEST_DIRECTORY"/lib-bundle.sh
10
11 if ! test_have_prereq PERL_TEST_HELPERS
12 then
13 skip_all='skipping fetch tests; Perl not available'
14 test_done
15 fi
16
17 test_expect_success setup '
18 echo >file original &&
19 git add file &&
20 git commit -a -m original &&
21 git branch -M main
22 '
23
24 test_expect_success "clone and setup child repos" '
25 git clone . one &&
26 (
27 cd one &&
28 echo >file updated by one &&
29 git commit -a -m "updated by one"
30 ) &&
31 git clone . two &&
32 (
33 cd two &&
34 git config branch.main.remote one &&
35 git config remote.one.url ../one/.git/ &&
36 git config remote.one.fetch refs/heads/main:refs/heads/one
37 ) &&
38 git clone . three &&
39 (
40 cd three &&
41 git config set remote.two.url ../two/.git/ &&
42 git config set remote.two.fetch refs/heads/main:refs/heads/two &&
43 git config set --append remote.two.fetch refs/heads/one:refs/heads/one &&
44 git config set branch.main.remote two &&
45 git config set branch.main.merge refs/heads/one
46 ) &&
47 git clone . bundle &&
48 git clone . seven &&
49 git clone --ref-format=reftable . case_sensitive &&
50 (
51 cd case_sensitive &&
52 git branch branch1 &&
53 git branch bRanch1
54 ) &&
55 git clone --ref-format=reftable . case_sensitive_fd &&
56 (
57 cd case_sensitive_fd &&
58 git branch foo/bar &&
59 git branch Foo
60 ) &&
61 git clone --ref-format=reftable . case_sensitive_df &&
62 (
63 cd case_sensitive_df &&
64 git branch Foo/bar &&
65 git branch foo
66 )
67 '
68
69 test_expect_success "fetch test" '
70 echo >file updated by origin &&
71 git commit -a -m "updated by origin" &&
72 (
73 cd two &&
74 git fetch &&
75 git rev-parse --verify refs/heads/one &&
76 mine=$(git rev-parse refs/heads/one) &&
77 his=$(cd ../one && git rev-parse refs/heads/main) &&
78 test "z$mine" = "z$his"
79 )
80 '
81
82 test_expect_success "fetch test for-merge" '
83 (
84 cd three &&
85 git fetch &&
86 git rev-parse --verify refs/heads/two &&
87 git rev-parse --verify refs/heads/one &&
88 main_in_two=$(cd ../two && git rev-parse main) &&
89 one_in_two=$(cd ../two && git rev-parse one) &&
90 {
91 echo "$one_in_two " &&
92 echo "$main_in_two not-for-merge"
93 } >expected &&
94 cut -f -2 .git/FETCH_HEAD >actual &&
95 test_cmp expected actual
96 )
97 '
98
99 test_expect_success "fetch test remote HEAD" '
100 (
101 cd two &&
102 git fetch &&
103 git rev-parse --verify refs/remotes/origin/HEAD &&
104 git rev-parse --verify refs/remotes/origin/main &&
105 head=$(git rev-parse refs/remotes/origin/HEAD) &&
106 branch=$(git rev-parse refs/remotes/origin/main) &&
107 test "z$head" = "z$branch"
108 )
109 '
110
111 test_expect_success "fetch test remote HEAD in bare repository" '
112 test_when_finished rm -rf barerepo &&
113 (
114 git init --bare barerepo &&
115 cd barerepo &&
116 git remote add upstream ../two &&
117 git fetch upstream &&
118 git rev-parse --verify refs/remotes/upstream/HEAD &&
119 git rev-parse --verify refs/remotes/upstream/main &&
120 head=$(git rev-parse refs/remotes/upstream/HEAD) &&
121 branch=$(git rev-parse refs/remotes/upstream/main) &&
122 test "z$head" = "z$branch"
123 )
124 '
125
126
127 test_expect_success "fetch test remote HEAD change" '
128 (
129 cd two &&
130 git switch -c other &&
131 git push -u origin other &&
132 git rev-parse --verify refs/remotes/origin/HEAD &&
133 git rev-parse --verify refs/remotes/origin/main &&
134 git rev-parse --verify refs/remotes/origin/other &&
135 git remote set-head origin other &&
136 git fetch &&
137 head=$(git rev-parse refs/remotes/origin/HEAD) &&
138 branch=$(git rev-parse refs/remotes/origin/other) &&
139 test "z$head" = "z$branch"
140 )
141 '
142
143 test_expect_success "fetch test default followRemoteHEAD never" '
144 git -C two update-ref --no-deref -d refs/remotes/origin/HEAD &&
145 test_config -C two fetch.followRemoteHEAD "never" &&
146 GIT_TRACE_PACKET=$PWD/trace.out git -C two fetch &&
147 # Confirm that we do not even ask for HEAD when we are
148 # not going to act on it.
149 test_grep ! "ref-prefix HEAD" trace.out &&
150 test_must_fail git -C two rev-parse --verify refs/remotes/origin/HEAD
151 '
152
153 test_expect_success "fetch test followRemoteHEAD never" '
154 git -C two update-ref --no-deref -d refs/remotes/origin/HEAD &&
155 test_config -C two remote.origin.followRemoteHEAD "never" &&
156 GIT_TRACE_PACKET=$PWD/trace.out git -C two fetch &&
157 # Confirm that we do not even ask for HEAD when we are
158 # not going to act on it.
159 test_grep ! "ref-prefix HEAD" trace.out &&
160 test_must_fail git -C two rev-parse --verify refs/remotes/origin/HEAD
161 '
162
163 test_expect_success "fetch test default followRemoteHEAD warn no change" '
164 git -C two rev-parse --verify refs/remotes/origin/other &&
165 git -C two remote set-head origin other &&
166 git -C two rev-parse --verify refs/remotes/origin/HEAD &&
167 git -C two rev-parse --verify refs/remotes/origin/main &&
168 test_config -C two fetch.followRemoteHEAD "warn" &&
169 git -C two fetch >output &&
170 echo "${SQ}HEAD${SQ} at ${SQ}origin${SQ} is ${SQ}main${SQ}," \
171 "but we have ${SQ}other${SQ} locally." >expect &&
172 test_cmp expect output &&
173 head=$(git -C two rev-parse refs/remotes/origin/HEAD) &&
174 branch=$(git -C two rev-parse refs/remotes/origin/other) &&
175 test "z$head" = "z$branch"
176 '
177
178 test_expect_success "fetch test followRemoteHEAD warn no change" '
179 git -C two rev-parse --verify refs/remotes/origin/other &&
180 git -C two remote set-head origin other &&
181 git -C two rev-parse --verify refs/remotes/origin/HEAD &&
182 git -C two rev-parse --verify refs/remotes/origin/main &&
183 test_config -C two remote.origin.followRemoteHEAD "warn" &&
184 git -C two fetch >output &&
185 echo "${SQ}HEAD${SQ} at ${SQ}origin${SQ} is ${SQ}main${SQ}," \
186 "but we have ${SQ}other${SQ} locally." >expect &&
187 test_cmp expect output &&
188 head=$(git -C two rev-parse refs/remotes/origin/HEAD) &&
189 branch=$(git -C two rev-parse refs/remotes/origin/other) &&
190 test "z$head" = "z$branch"
191 '
192
193 test_expect_success "fetch test default followRemoteHEAD warn create" '
194 git -C two update-ref --no-deref -d refs/remotes/origin/HEAD &&
195 test_config -C two fetch.followRemoteHEAD "warn" &&
196 git -C two rev-parse --verify refs/remotes/origin/main &&
197 output=$(git -C two fetch) &&
198 test "z" = "z$output" &&
199 head=$(git -C two rev-parse refs/remotes/origin/HEAD) &&
200 branch=$(git -C two rev-parse refs/remotes/origin/main) &&
201 test "z$head" = "z$branch"
202 '
203
204 test_expect_success "fetch test followRemoteHEAD warn create" '
205 git -C two update-ref --no-deref -d refs/remotes/origin/HEAD &&
206 test_config -C two remote.origin.followRemoteHEAD "warn" &&
207 git -C two rev-parse --verify refs/remotes/origin/main &&
208 output=$(git -C two fetch) &&
209 test "z" = "z$output" &&
210 head=$(git -C two rev-parse refs/remotes/origin/HEAD) &&
211 branch=$(git -C two rev-parse refs/remotes/origin/main) &&
212 test "z$head" = "z$branch"
213 '
214
215 test_expect_success "fetch test default followRemoteHEAD warn detached" '
216 git -C two update-ref --no-deref -d refs/remotes/origin/HEAD &&
217 git -C two update-ref refs/remotes/origin/HEAD HEAD &&
218 HEAD=$(git -C two log --pretty="%H") &&
219 test_config -C two fetch.followRemoteHEAD "warn" &&
220 git -C two fetch >output &&
221 echo "${SQ}HEAD${SQ} at ${SQ}origin${SQ} is ${SQ}main${SQ}," \
222 "but we have a detached HEAD pointing to" \
223 "${SQ}${HEAD}${SQ} locally." >expect &&
224 test_cmp expect output
225 '
226
227 test_expect_success "fetch test followRemoteHEAD warn detached" '
228 git -C two update-ref --no-deref -d refs/remotes/origin/HEAD &&
229 git -C two update-ref refs/remotes/origin/HEAD HEAD &&
230 HEAD=$(git -C two log --pretty="%H") &&
231 test_config -C two remote.origin.followRemoteHEAD "warn" &&
232 git -C two fetch >output &&
233 echo "${SQ}HEAD${SQ} at ${SQ}origin${SQ} is ${SQ}main${SQ}," \
234 "but we have a detached HEAD pointing to" \
235 "${SQ}${HEAD}${SQ} locally." >expect &&
236 test_cmp expect output
237 '
238
239 test_expect_success "fetch test default followRemoteHEAD warn quiet" '
240 git -C two rev-parse --verify refs/remotes/origin/other &&
241 git -C two remote set-head origin other &&
242 git -C two rev-parse --verify refs/remotes/origin/HEAD &&
243 git -C two rev-parse --verify refs/remotes/origin/main &&
244 test_config -C two fetch.followRemoteHEAD "warn" &&
245 output=$(git -C two fetch --quiet) &&
246 test "z" = "z$output" &&
247 head=$(git -C two rev-parse refs/remotes/origin/HEAD) &&
248 branch=$(git -C two rev-parse refs/remotes/origin/other) &&
249 test "z$head" = "z$branch"
250 '
251
252 test_expect_success "fetch test followRemoteHEAD warn quiet" '
253 git -C two rev-parse --verify refs/remotes/origin/other &&
254 git -C two remote set-head origin other &&
255 git -C two rev-parse --verify refs/remotes/origin/HEAD &&
256 git -C two rev-parse --verify refs/remotes/origin/main &&
257 test_config -C two remote.origin.followRemoteHEAD "warn" &&
258 output=$(git -C two fetch --quiet) &&
259 test "z" = "z$output" &&
260 head=$(git -C two rev-parse refs/remotes/origin/HEAD) &&
261 branch=$(git -C two rev-parse refs/remotes/origin/other) &&
262 test "z$head" = "z$branch"
263 '
264
265 test_expect_success "fetch test followRemoteHEAD warn-if-not-branch branch is same" '
266 git -C two rev-parse --verify refs/remotes/origin/other &&
267 git -C two remote set-head origin other &&
268 git -C two rev-parse --verify refs/remotes/origin/HEAD &&
269 git -C two rev-parse --verify refs/remotes/origin/main &&
270 test_config -C two remote.origin.followRemoteHEAD "warn-if-not-main" &&
271 actual=$(git -C two fetch) &&
272 test "z" = "z$actual" &&
273 head=$(git -C two rev-parse refs/remotes/origin/HEAD) &&
274 branch=$(git -C two rev-parse refs/remotes/origin/other) &&
275 test "z$head" = "z$branch"
276 '
277
278 test_expect_success "fetch test followRemoteHEAD warn-if-not-branch branch is different" '
279 git -C two rev-parse --verify refs/remotes/origin/other &&
280 git -C two remote set-head origin other &&
281 git -C two rev-parse --verify refs/remotes/origin/HEAD &&
282 git -C two rev-parse --verify refs/remotes/origin/main &&
283 test_config -C two remote.origin.followRemoteHEAD "warn-if-not-some/different-branch" &&
284 git -C two fetch >actual &&
285 echo "${SQ}HEAD${SQ} at ${SQ}origin${SQ} is ${SQ}main${SQ}," \
286 "but we have ${SQ}other${SQ} locally." >expect &&
287 test_cmp expect actual &&
288 head=$(git -C two rev-parse refs/remotes/origin/HEAD) &&
289 branch=$(git -C two rev-parse refs/remotes/origin/other) &&
290 test "z$head" = "z$branch"
291 '
292
293 test_expect_success "fetch test default followRemoteHEAD always" '
294 git -C two rev-parse --verify refs/remotes/origin/other &&
295 git -C two remote set-head origin other &&
296 git -C two rev-parse --verify refs/remotes/origin/HEAD &&
297 git -C two rev-parse --verify refs/remotes/origin/main &&
298 test_config -C two fetch.followRemoteHEAD "always" &&
299 git -C two fetch &&
300 head=$(git -C two rev-parse refs/remotes/origin/HEAD) &&
301 branch=$(git -C two rev-parse refs/remotes/origin/main) &&
302 test "z$head" = "z$branch"
303 '
304
305 test_expect_success "fetch test followRemoteHEAD always" '
306 git -C two rev-parse --verify refs/remotes/origin/other &&
307 git -C two remote set-head origin other &&
308 git -C two rev-parse --verify refs/remotes/origin/HEAD &&
309 git -C two rev-parse --verify refs/remotes/origin/main &&
310 test_config -C two remote.origin.followRemoteHEAD "always" &&
311 git -C two fetch &&
312 head=$(git -C two rev-parse refs/remotes/origin/HEAD) &&
313 branch=$(git -C two rev-parse refs/remotes/origin/main) &&
314 test "z$head" = "z$branch"
315 '
316
317 test_expect_success 'per-remote followRemoteHEAD takes priority over fetch default' '
318 git -C two rev-parse --verify refs/remotes/origin/other &&
319 git -C two remote set-head origin other &&
320 git -C two rev-parse --verify refs/remotes/origin/HEAD &&
321 git -C two rev-parse --verify refs/remotes/origin/main &&
322 test_config -C two fetch.followRemoteHEAD "never" &&
323 test_config -C two remote.origin.followRemoteHEAD "always" &&
324 git -C two fetch &&
325 head=$(git -C two rev-parse refs/remotes/origin/HEAD) &&
326 branch=$(git -C two rev-parse refs/remotes/origin/main) &&
327 test "z$head" = "z$branch"
328 '
329
330 test_expect_success 'default followRemoteHEAD does not kick in with refspecs' '
331 git -C two remote set-head origin other &&
332 test_config -C two fetch.followRemoteHEAD always &&
333 git -C two fetch origin refs/heads/main:refs/remotes/origin/main &&
334 echo refs/remotes/origin/other >expect &&
335 git -C two symbolic-ref refs/remotes/origin/HEAD >actual &&
336 test_cmp expect actual
337 '
338
339 test_expect_success 'followRemoteHEAD does not kick in with refspecs' '
340 git -C two remote set-head origin other &&
341 test_config -C two remote.origin.followRemoteHEAD always &&
342 git -C two fetch origin refs/heads/main:refs/remotes/origin/main &&
343 echo refs/remotes/origin/other >expect &&
344 git -C two symbolic-ref refs/remotes/origin/HEAD >actual &&
345 test_cmp expect actual
346 '
347
348 test_expect_success 'default followRemoteHEAD create does not overwrite dangling symref' '
349 test_when_finished "git -C two remote remove custom-head" &&
350 git -C two remote add -m does-not-exist custom-head ../one &&
351 test_config -C two fetch.followRemoteHEAD create &&
352 git -C two fetch custom-head &&
353 echo refs/remotes/custom-head/does-not-exist >expect &&
354 git -C two symbolic-ref refs/remotes/custom-head/HEAD >actual &&
355 test_cmp expect actual
356 '
357
358 test_expect_success 'followRemoteHEAD create does not overwrite dangling symref' '
359 test_when_finished "git -C two remote remove custom-head" &&
360 git -C two remote add -m does-not-exist custom-head ../one &&
361 test_config -C two remote.custom-head.followRemoteHEAD create &&
362 git -C two fetch custom-head &&
363 echo refs/remotes/custom-head/does-not-exist >expect &&
364 git -C two symbolic-ref refs/remotes/custom-head/HEAD >actual &&
365 test_cmp expect actual
366 '
367
368 test_expect_success 'fetch --prune on its own works as expected' '
369 git clone . prune &&
370 (
371 cd prune &&
372 git update-ref refs/remotes/origin/extrabranch main &&
373
374 git fetch --prune origin &&
375 test_must_fail git rev-parse origin/extrabranch
376 )
377 '
378
379 test_expect_success 'fetch --prune with a branch name keeps branches' '
380 git clone . prune-branch &&
381 (
382 cd prune-branch &&
383 git update-ref refs/remotes/origin/extrabranch main &&
384
385 git fetch --prune origin main &&
386 git rev-parse origin/extrabranch
387 )
388 '
389
390 test_expect_success 'fetch --prune with a namespace keeps other namespaces' '
391 git clone . prune-namespace &&
392 (
393 cd prune-namespace &&
394
395 git fetch --prune origin refs/heads/a/*:refs/remotes/origin/a/* &&
396 git rev-parse origin/main
397 )
398 '
399
400 test_expect_success 'fetch --prune handles overlapping refspecs' '
401 git update-ref refs/pull/42/head main &&
402 git clone . prune-overlapping &&
403 (
404 cd prune-overlapping &&
405 git config --add remote.origin.fetch refs/pull/*/head:refs/remotes/origin/pr/* &&
406
407 git fetch --prune origin &&
408 git rev-parse origin/main &&
409 git rev-parse origin/pr/42 &&
410
411 git config --unset-all remote.origin.fetch &&
412 git config remote.origin.fetch refs/pull/*/head:refs/remotes/origin/pr/* &&
413 git config --add remote.origin.fetch refs/heads/*:refs/remotes/origin/* &&
414
415 git fetch --prune origin &&
416 git rev-parse origin/main &&
417 git rev-parse origin/pr/42
418 )
419 '
420
421 test_expect_success 'fetch --prune --tags prunes branches but not tags' '
422 git clone . prune-tags &&
423 (
424 cd prune-tags &&
425 git tag sometag main &&
426 # Create what looks like a remote-tracking branch from an earlier
427 # fetch that has since been deleted from the remote:
428 git update-ref refs/remotes/origin/fake-remote main &&
429
430 git fetch --prune --tags origin &&
431 git rev-parse origin/main &&
432 test_must_fail git rev-parse origin/fake-remote &&
433 git rev-parse sometag
434 )
435 '
436
437 test_expect_success 'fetch --prune --tags with branch does not prune other things' '
438 git clone . prune-tags-branch &&
439 (
440 cd prune-tags-branch &&
441 git tag sometag main &&
442 git update-ref refs/remotes/origin/extrabranch main &&
443
444 git fetch --prune --tags origin main &&
445 git rev-parse origin/extrabranch &&
446 git rev-parse sometag
447 )
448 '
449
450 test_expect_success 'fetch --prune --tags with refspec prunes based on refspec' '
451 git clone . prune-tags-refspec &&
452 (
453 cd prune-tags-refspec &&
454 git tag sometag main &&
455 git update-ref refs/remotes/origin/foo/otherbranch main &&
456 git update-ref refs/remotes/origin/extrabranch main &&
457
458 git fetch --prune --tags origin refs/heads/foo/*:refs/remotes/origin/foo/* &&
459 test_must_fail git rev-parse refs/remotes/origin/foo/otherbranch &&
460 git rev-parse origin/extrabranch &&
461 git rev-parse sometag
462 )
463 '
464
465 test_expect_success 'fetch --tags gets tags even without a configured remote' '
466 REMOTE="$(pwd)/test_tag_1" &&
467 git init test_tag_1 &&
468 (
469 cd test_tag_1 &&
470 test_commit foo
471 ) &&
472 git init test_tag_2 &&
473 (
474 cd test_tag_2 &&
475 git fetch --tags "file://$REMOTE" &&
476 echo "foo" >expect &&
477 git tag >actual &&
478 test_cmp expect actual
479 )
480 '
481
482 test_expect_success REFFILES 'fetch --prune fails to delete branches' '
483 git clone . prune-fail &&
484 (
485 cd prune-fail &&
486 git update-ref refs/remotes/origin/extrabranch main &&
487 git pack-refs --all &&
488 : this will prevent --prune from locking packed-refs for deleting refs, but adding loose refs still succeeds &&
489 >.git/packed-refs.new &&
490
491 test_must_fail git fetch --prune origin
492 )
493 '
494
495 test_expect_success 'fetch --atomic works with a single branch' '
496 test_when_finished "rm -rf atomic" &&
497
498 git clone . atomic &&
499 git branch atomic-branch &&
500 oid=$(git rev-parse atomic-branch) &&
501 echo "$oid" >expected &&
502
503 git -C atomic fetch --atomic origin &&
504 git -C atomic rev-parse origin/atomic-branch >actual &&
505 test_cmp expected actual &&
506 test $oid = "$(git -C atomic rev-parse --verify FETCH_HEAD)"
507 '
508
509 test_expect_success 'fetch --atomic works with multiple branches' '
510 test_when_finished "rm -rf atomic" &&
511
512 git clone . atomic &&
513 git branch atomic-branch-1 &&
514 git branch atomic-branch-2 &&
515 git branch atomic-branch-3 &&
516 git rev-parse refs/heads/atomic-branch-1 refs/heads/atomic-branch-2 refs/heads/atomic-branch-3 >actual &&
517
518 git -C atomic fetch --atomic origin &&
519 git -C atomic rev-parse refs/remotes/origin/atomic-branch-1 refs/remotes/origin/atomic-branch-2 refs/remotes/origin/atomic-branch-3 >expected &&
520 test_cmp expected actual
521 '
522
523 test_expect_success 'fetch --atomic works with mixed branches and tags' '
524 test_when_finished "rm -rf atomic" &&
525
526 git clone . atomic &&
527 git branch atomic-mixed-branch &&
528 git tag atomic-mixed-tag &&
529 git rev-parse refs/heads/atomic-mixed-branch refs/tags/atomic-mixed-tag >actual &&
530
531 git -C atomic fetch --tags --atomic origin &&
532 git -C atomic rev-parse refs/remotes/origin/atomic-mixed-branch refs/tags/atomic-mixed-tag >expected &&
533 test_cmp expected actual
534 '
535
536 test_expect_success 'fetch --atomic prunes references' '
537 test_when_finished "rm -rf atomic" &&
538
539 git branch atomic-prune-delete &&
540 git clone . atomic &&
541 git branch --delete atomic-prune-delete &&
542 git branch atomic-prune-create &&
543 git rev-parse refs/heads/atomic-prune-create >actual &&
544
545 git -C atomic fetch --prune --atomic origin &&
546 test_must_fail git -C atomic rev-parse refs/remotes/origin/atomic-prune-delete &&
547 git -C atomic rev-parse refs/remotes/origin/atomic-prune-create >expected &&
548 test_cmp expected actual
549 '
550
551 test_expect_success 'fetch --atomic aborts with non-fast-forward update' '
552 test_when_finished "rm -rf atomic" &&
553
554 git branch atomic-non-ff &&
555 git clone . atomic &&
556 git rev-parse HEAD >actual &&
557
558 git branch atomic-new-branch &&
559 parent_commit=$(git rev-parse atomic-non-ff~) &&
560 git update-ref refs/heads/atomic-non-ff $parent_commit &&
561
562 test_must_fail git -C atomic fetch --atomic origin refs/heads/*:refs/remotes/origin/* &&
563 test_must_fail git -C atomic rev-parse refs/remotes/origin/atomic-new-branch &&
564 git -C atomic rev-parse refs/remotes/origin/atomic-non-ff >expected &&
565 test_cmp expected actual &&
566 test_must_be_empty atomic/.git/FETCH_HEAD
567 '
568
569 test_expect_success 'fetch --atomic executes a single reference transaction only' '
570 test_when_finished "rm -rf atomic" &&
571
572 git clone . atomic &&
573 git branch atomic-hooks-1 &&
574 git branch atomic-hooks-2 &&
575 head_oid=$(git rev-parse HEAD) &&
576
577 cat >expected <<-EOF &&
578 preparing
579 $ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-1
580 $ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-2
581 prepared
582 $ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-1
583 $ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-2
584 committed
585 $ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-1
586 $ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-2
587 preparing
588 $ZERO_OID ref:refs/remotes/origin/main refs/remotes/origin/HEAD
589 EOF
590
591 rm -f atomic/actual &&
592 test_hook -C atomic reference-transaction <<-\EOF &&
593 ( echo "$*" && cat ) >>actual
594 EOF
595
596 git -C atomic fetch --atomic origin &&
597 test_cmp expected atomic/actual
598 '
599
600 test_expect_success 'fetch --atomic aborts all reference updates if hook aborts' '
601 test_when_finished "rm -rf atomic" &&
602
603 git clone . atomic &&
604 git branch atomic-hooks-abort-1 &&
605 git branch atomic-hooks-abort-2 &&
606 git branch atomic-hooks-abort-3 &&
607 git tag atomic-hooks-abort &&
608 head_oid=$(git rev-parse HEAD) &&
609
610 cat >expected <<-EOF &&
611 preparing
612 $ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-abort-1
613 $ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-abort-2
614 $ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-abort-3
615 $ZERO_OID $head_oid refs/tags/atomic-hooks-abort
616 aborted
617 $ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-abort-1
618 $ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-abort-2
619 $ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-abort-3
620 $ZERO_OID $head_oid refs/tags/atomic-hooks-abort
621 EOF
622
623 rm -f atomic/actual &&
624 test_hook -C atomic/.git reference-transaction <<-\EOF &&
625 ( echo "$*" && cat ) >>actual
626 exit 1
627 EOF
628
629 git -C atomic for-each-ref >expected-refs &&
630 test_must_fail git -C atomic fetch --tags --atomic origin &&
631 git -C atomic for-each-ref >actual-refs &&
632 test_cmp expected-refs actual-refs &&
633 test_must_be_empty atomic/.git/FETCH_HEAD
634 '
635
636 test_expect_success 'fetch --atomic --append appends to FETCH_HEAD' '
637 test_when_finished "rm -rf atomic" &&
638
639 git clone . atomic &&
640 oid=$(git rev-parse HEAD) &&
641
642 git branch atomic-fetch-head-1 &&
643 git -C atomic fetch --atomic origin atomic-fetch-head-1 &&
644 test_line_count = 1 atomic/.git/FETCH_HEAD &&
645
646 git branch atomic-fetch-head-2 &&
647 git -C atomic fetch --atomic --append origin atomic-fetch-head-2 &&
648 test_line_count = 2 atomic/.git/FETCH_HEAD &&
649 cp atomic/.git/FETCH_HEAD expected &&
650
651 test_hook -C atomic reference-transaction <<-\EOF &&
652 exit 1
653 EOF
654
655 git branch atomic-fetch-head-3 &&
656 test_must_fail git -C atomic fetch --atomic --append origin atomic-fetch-head-3 &&
657 test_cmp expected atomic/.git/FETCH_HEAD
658 '
659
660 test_expect_success REFFILES 'fetch --atomic fails transaction if reference locked' '
661 test_when_finished "rm -rf upstream repo" &&
662
663 git init upstream &&
664 git -C upstream commit --allow-empty -m 1 &&
665 git -C upstream switch -c foobar &&
666 git clone --mirror upstream repo &&
667 git -C upstream commit --allow-empty -m 2 &&
668 touch repo/refs/heads/foobar.lock &&
669
670 test_must_fail git -C repo fetch --atomic origin
671 '
672
673 test_expect_success '--refmap="" ignores configured refspec' '
674 git clone . remote-refs &&
675 git -C remote-refs rev-parse remotes/origin/main >old &&
676 git -C remote-refs update-ref refs/remotes/origin/main main~1 &&
677 git -C remote-refs rev-parse remotes/origin/main >new &&
678 git -C remote-refs fetch --refmap= origin "+refs/heads/*:refs/hidden/origin/*" &&
679 git -C remote-refs rev-parse remotes/origin/main >actual &&
680 test_cmp new actual &&
681 git -C remote-refs fetch origin &&
682 git -C remote-refs rev-parse remotes/origin/main >actual &&
683 test_cmp old actual
684 '
685
686 test_expect_success '--refmap="" and --prune' '
687 git -C remote-refs update-ref refs/remotes/origin/foo/otherbranch main &&
688 git -C remote-refs update-ref refs/hidden/foo/otherbranch main &&
689 git -C remote-refs fetch --prune --refmap="" origin +refs/heads/*:refs/hidden/* &&
690 git -C remote-refs rev-parse remotes/origin/foo/otherbranch &&
691 test_must_fail git -C remote-refs rev-parse refs/hidden/foo/otherbranch &&
692 git -C remote-refs fetch --prune origin &&
693 test_must_fail git -C remote-refs rev-parse remotes/origin/foo/otherbranch
694 '
695
696 test_expect_success 'fetch tags when there is no tags' '
697
698 git init notags &&
699 git -C notags fetch -t ..
700
701 '
702
703 test_expect_success 'fetch following tags' '
704
705 git tag -a -m "annotated" anno HEAD &&
706 git tag light HEAD &&
707
708 git init four &&
709 (
710 cd four &&
711 git fetch .. :track &&
712 git show-ref --verify refs/tags/anno &&
713 git show-ref --verify refs/tags/light
714 )
715 '
716
717 test_expect_success 'fetch uses remote ref names to describe new refs' '
718 git init descriptive &&
719 (
720 cd descriptive &&
721 git config remote.o.url .. &&
722 git config remote.o.fetch "refs/heads/*:refs/crazyheads/*" &&
723 git config --add remote.o.fetch "refs/others/*:refs/heads/*" &&
724 git fetch o
725 ) &&
726 git tag -a -m "Descriptive tag" descriptive-tag &&
727 git branch descriptive-branch &&
728 git checkout descriptive-branch &&
729 echo "Nuts" >crazy &&
730 git add crazy &&
731 git commit -a -m "descriptive commit" &&
732 git update-ref refs/others/crazy HEAD &&
733 (
734 cd descriptive &&
735 git fetch o 2>actual &&
736 test_grep "new branch.* -> refs/crazyheads/descriptive-branch$" actual &&
737 test_grep "new tag.* -> descriptive-tag$" actual &&
738 test_grep "new ref.* -> crazy$" actual
739 ) &&
740 git checkout main
741 '
742
743 test_expect_success 'fetch must not resolve short tag name' '
744
745 git init five &&
746 test_must_fail git -C five fetch .. anno:five
747
748 '
749
750 test_expect_success 'fetch can now resolve short remote name' '
751
752 git update-ref refs/remotes/six/HEAD HEAD &&
753
754 git init six &&
755 git -C six fetch .. six:six
756 '
757
758 test_expect_success 'create bundle 1' '
759 echo >file updated again by origin &&
760 git commit -a -m "tip" &&
761 git bundle create --version=3 bundle1 main^..main
762 '
763
764 test_expect_success 'header of bundle looks right' '
765 cat >expect <<-EOF &&
766 # v3 git bundle
767 @object-format=$(test_oid algo)
768 -OID updated by origin
769 OID refs/heads/main
770
771 EOF
772 sed -e "s/$OID_REGEX/OID/g" -e "5q" bundle1 >actual &&
773 test_cmp expect actual
774 '
775
776 test_expect_success 'create bundle 2' '
777 git bundle create bundle2 main~2..main
778 '
779
780 test_expect_success 'unbundle 1' '
781 (
782 cd bundle &&
783 git checkout -b some-branch &&
784 test_must_fail git fetch bundle1 main:main
785 )
786 '
787
788
789 test_expect_success 'bundle 1 has only 3 files ' '
790 test_bundle_object_count bundle1 3
791 '
792
793 test_expect_success 'unbundle 2' '
794 (
795 cd bundle &&
796 git fetch ../bundle2 main:main &&
797 test "tip" = "$(git log -1 --pretty=oneline main | cut -d" " -f2)"
798 )
799 '
800
801 test_expect_success 'bundle does not prerequisite objects' '
802 touch file2 &&
803 git add file2 &&
804 git commit -m add.file2 file2 &&
805 git bundle create bundle3 -1 HEAD &&
806 test_bundle_object_count bundle3 3
807 '
808
809 test_expect_success 'bundle should be able to create a full history' '
810
811 git tag -a -m "1.0" v1.0 main &&
812 git bundle create bundle4 v1.0
813
814 '
815
816 test_expect_success 'fetch with a non-applying branch.<name>.merge' '
817 git config branch.main.remote yeti &&
818 git config branch.main.merge refs/heads/bigfoot &&
819 git config remote.blub.url one &&
820 git config remote.blub.fetch "refs/heads/*:refs/remotes/one/*" &&
821 git fetch blub
822 '
823
824 # URL supplied to fetch does not match the url of the configured branch's remote
825 test_expect_success 'fetch from GIT URL with a non-applying branch.<name>.merge [1]' '
826 one_head=$(cd one && git rev-parse HEAD) &&
827 this_head=$(git rev-parse HEAD) &&
828 rm .git/FETCH_HEAD &&
829 git fetch one &&
830 test $one_head = "$(git rev-parse --verify FETCH_HEAD)" &&
831 test $this_head = "$(git rev-parse --verify HEAD)"
832 '
833
834 # URL supplied to fetch matches the url of the configured branch's remote and
835 # the merge spec matches the branch the remote HEAD points to
836 test_expect_success 'fetch from GIT URL with a non-applying branch.<name>.merge [2]' '
837 one_ref=$(cd one && git symbolic-ref HEAD) &&
838 git config branch.main.remote blub &&
839 git config branch.main.merge "$one_ref" &&
840 rm .git/FETCH_HEAD &&
841 git fetch one &&
842 test $one_head = "$(git rev-parse --verify FETCH_HEAD)" &&
843 test $this_head = "$(git rev-parse --verify HEAD)"
844 '
845
846 # URL supplied to fetch matches the url of the configured branch's remote, but
847 # the merge spec does not match the branch the remote HEAD points to
848 test_expect_success 'fetch from GIT URL with a non-applying branch.<name>.merge [3]' '
849 git config branch.main.merge "${one_ref}_not" &&
850 rm .git/FETCH_HEAD &&
851 git fetch one &&
852 test $one_head = "$(git rev-parse --verify FETCH_HEAD)" &&
853 test $this_head = "$(git rev-parse --verify HEAD)"
854 '
855
856 # the strange name is: a\!'b
857 test_expect_success 'quoting of a strangely named repo' '
858 test_must_fail git fetch "a\\!'\''b" > result 2>&1 &&
859 test_grep "fatal: '\''a\\\\!'\''b'\''" result
860 '
861
862 test_expect_success 'bundle should record HEAD correctly' '
863
864 git bundle create bundle5 HEAD main &&
865 git bundle list-heads bundle5 >actual &&
866 for h in HEAD refs/heads/main
867 do
868 echo "$(git rev-parse --verify $h) $h" || return 1
869 done >expect &&
870 test_cmp expect actual
871
872 '
873
874 test_expect_success 'mark initial state of origin/main' '
875 (
876 cd three &&
877 git tag base-origin-main refs/remotes/origin/main
878 )
879 '
880
881 test_expect_success 'explicit fetch should update tracking' '
882
883 git branch -f side &&
884 (
885 cd three &&
886 git update-ref refs/remotes/origin/main base-origin-main &&
887 o=$(git rev-parse --verify refs/remotes/origin/main) &&
888 git fetch origin main &&
889 n=$(git rev-parse --verify refs/remotes/origin/main) &&
890 test "$o" != "$n" &&
891 test_must_fail git rev-parse --verify refs/remotes/origin/side
892 )
893 '
894
895 test_expect_success 'explicit pull should update tracking' '
896
897 git branch -f side &&
898 (
899 cd three &&
900 git update-ref refs/remotes/origin/main base-origin-main &&
901 o=$(git rev-parse --verify refs/remotes/origin/main) &&
902 git pull origin main &&
903 n=$(git rev-parse --verify refs/remotes/origin/main) &&
904 test "$o" != "$n" &&
905 test_must_fail git rev-parse --verify refs/remotes/origin/side
906 )
907 '
908
909 test_expect_success 'explicit --refmap is allowed only with command-line refspec' '
910 (
911 cd three &&
912 test_must_fail git fetch --refmap="*:refs/remotes/none/*"
913 )
914 '
915
916 test_expect_success 'explicit --refmap option overrides remote.*.fetch' '
917 git branch -f side &&
918 (
919 cd three &&
920 git update-ref refs/remotes/origin/main base-origin-main &&
921 o=$(git rev-parse --verify refs/remotes/origin/main) &&
922 git fetch --refmap="refs/heads/*:refs/remotes/other/*" origin main &&
923 n=$(git rev-parse --verify refs/remotes/origin/main) &&
924 test "$o" = "$n" &&
925 test_must_fail git rev-parse --verify refs/remotes/origin/side &&
926 git rev-parse --verify refs/remotes/other/main
927 )
928 '
929
930 test_expect_success 'explicitly empty --refmap option disables remote.*.fetch' '
931 git branch -f side &&
932 (
933 cd three &&
934 git update-ref refs/remotes/origin/main base-origin-main &&
935 o=$(git rev-parse --verify refs/remotes/origin/main) &&
936 git fetch --refmap="" origin main &&
937 n=$(git rev-parse --verify refs/remotes/origin/main) &&
938 test "$o" = "$n" &&
939 test_must_fail git rev-parse --verify refs/remotes/origin/side
940 )
941 '
942
943 test_expect_success 'configured fetch updates tracking' '
944
945 git branch -f side &&
946 (
947 cd three &&
948 git update-ref refs/remotes/origin/main base-origin-main &&
949 o=$(git rev-parse --verify refs/remotes/origin/main) &&
950 git fetch origin &&
951 n=$(git rev-parse --verify refs/remotes/origin/main) &&
952 test "$o" != "$n" &&
953 git rev-parse --verify refs/remotes/origin/side
954 )
955 '
956
957 test_expect_success 'non-matching refspecs do not confuse tracking update' '
958 git update-ref refs/odd/location HEAD &&
959 (
960 cd three &&
961 git update-ref refs/remotes/origin/main base-origin-main &&
962 git config --add remote.origin.fetch \
963 refs/odd/location:refs/remotes/origin/odd &&
964 o=$(git rev-parse --verify refs/remotes/origin/main) &&
965 git fetch origin main &&
966 n=$(git rev-parse --verify refs/remotes/origin/main) &&
967 test "$o" != "$n" &&
968 test_must_fail git rev-parse --verify refs/remotes/origin/odd
969 )
970 '
971
972 test_expect_success 'pushing nonexistent branch by mistake should not segv' '
973
974 test_must_fail git push seven no:no
975
976 '
977
978 test_expect_success 'auto tag following fetches minimum' '
979
980 git clone .git follow &&
981 git checkout HEAD^0 &&
982 (
983 for i in 1 2 3 4 5 6 7
984 do
985 echo $i >>file &&
986 git commit -m $i -a &&
987 git tag -a -m $i excess-$i || exit 1
988 done
989 ) &&
990 git checkout main &&
991 (
992 cd follow &&
993 git fetch
994 )
995 '
996
997 test_expect_success 'refuse to fetch into the current branch' '
998
999 test_must_fail git fetch . side:main
1000
1001 '
1002
1003 test_expect_success 'fetch into the current branch with --update-head-ok' '
1004
1005 git fetch --update-head-ok . side:main
1006
1007 '
1008
1009 test_expect_success 'fetch --dry-run does not touch FETCH_HEAD, but still prints what would be written' '
1010 rm -f .git/FETCH_HEAD err &&
1011 git fetch --dry-run . 2>err &&
1012 ! test -f .git/FETCH_HEAD &&
1013 test_grep FETCH_HEAD err
1014 '
1015
1016 test_expect_success '--no-write-fetch-head does not touch FETCH_HEAD, and does not print what would be written' '
1017 rm -f .git/FETCH_HEAD err &&
1018 git fetch --no-write-fetch-head . 2>err &&
1019 ! test -f .git/FETCH_HEAD &&
1020 test_grep ! FETCH_HEAD err
1021 '
1022
1023 test_expect_success '--write-fetch-head gets defeated by --dry-run' '
1024 rm -f .git/FETCH_HEAD &&
1025 git fetch --dry-run --write-fetch-head . &&
1026 ! test -f .git/FETCH_HEAD
1027 '
1028
1029 test_expect_success "should be able to fetch with duplicate refspecs" '
1030 mkdir dups &&
1031 (
1032 cd dups &&
1033 git init &&
1034 git config branch.main.remote three &&
1035 git config remote.three.url ../three/.git &&
1036 git config remote.three.fetch +refs/heads/*:refs/remotes/origin/* &&
1037 git config --add remote.three.fetch +refs/heads/*:refs/remotes/origin/* &&
1038 git fetch three
1039 )
1040 '
1041
1042 test_expect_success 'LHS of refspec follows ref disambiguation rules' '
1043 mkdir lhs-ambiguous &&
1044 (
1045 cd lhs-ambiguous &&
1046 git init server &&
1047 test_commit -C server unwanted &&
1048 test_commit -C server wanted &&
1049
1050 git init client &&
1051
1052 # Check a name coming after "refs" alphabetically ...
1053 git -C server update-ref refs/heads/s wanted &&
1054 git -C server update-ref refs/heads/refs/heads/s unwanted &&
1055 git -C client fetch ../server +refs/heads/s:refs/heads/checkthis &&
1056 git -C server rev-parse wanted >expect &&
1057 git -C client rev-parse checkthis >actual &&
1058 test_cmp expect actual &&
1059
1060 # ... and one before.
1061 git -C server update-ref refs/heads/q wanted &&
1062 git -C server update-ref refs/heads/refs/heads/q unwanted &&
1063 git -C client fetch ../server +refs/heads/q:refs/heads/checkthis &&
1064 git -C server rev-parse wanted >expect &&
1065 git -C client rev-parse checkthis >actual &&
1066 test_cmp expect actual &&
1067
1068 # Tags are preferred over branches like refs/{heads,tags}/*
1069 git -C server update-ref refs/tags/t wanted &&
1070 git -C server update-ref refs/heads/t unwanted &&
1071 git -C client fetch ../server +t:refs/heads/checkthis &&
1072 git -C server rev-parse wanted >expect &&
1073 git -C client rev-parse checkthis >actual
1074 )
1075 '
1076
1077 test_expect_success 'fetch.writeCommitGraph' '
1078 git clone three write &&
1079 (
1080 cd three &&
1081 test_commit new
1082 ) &&
1083 (
1084 cd write &&
1085 git -c fetch.writeCommitGraph fetch origin &&
1086 test_path_is_file .git/objects/info/commit-graphs/commit-graph-chain
1087 )
1088 '
1089
1090 test_expect_success 'fetch.writeCommitGraph with submodules' '
1091 test_config_global protocol.file.allow always &&
1092 git clone dups super &&
1093 (
1094 cd super &&
1095 git submodule add "file://$TRASH_DIRECTORY/three" &&
1096 git commit -m "add submodule"
1097 ) &&
1098 git clone "super" super-clone &&
1099 (
1100 cd super-clone &&
1101 rm -rf .git/objects/info &&
1102 git -c fetch.writeCommitGraph=true fetch origin &&
1103 test_path_is_file .git/objects/info/commit-graphs/commit-graph-chain &&
1104 git -c fetch.writeCommitGraph=true fetch --recurse-submodules origin
1105 )
1106 '
1107
1108 # fetches from first configured url
1109 test_expect_success 'fetch from multiple configured URLs in single remote' '
1110 git init url1 &&
1111 git remote add multipleurls url1 &&
1112 git remote set-url --add multipleurls url2 &&
1113 git fetch multipleurls
1114 '
1115
1116 # configured prune tests
1117
1118 set_config_tristate () {
1119 # var=$1 val=$2
1120 case "$2" in
1121 unset)
1122 test_unconfig "$1"
1123 ;;
1124 *)
1125 git config "$1" "$2"
1126 key=$(echo $1 | sed -e 's/^remote\.origin/fetch/')
1127 git_fetch_c="$git_fetch_c -c $key=$2"
1128 ;;
1129 esac
1130 }
1131
1132 test_configured_prune () {
1133 test_configured_prune_type "$@" "name"
1134 test_configured_prune_type "$@" "link"
1135 }
1136
1137 test_configured_prune_type () {
1138 fetch_prune=$1
1139 remote_origin_prune=$2
1140 fetch_prune_tags=$3
1141 remote_origin_prune_tags=$4
1142 expected_branch=$5
1143 expected_tag=$6
1144 cmdline=$7
1145 mode=$8
1146
1147 if test -z "$cmdline_setup"
1148 then
1149 test_expect_success 'setup cmdline_setup variable for subsequent test' '
1150 remote_url="file://$(git -C one config remote.origin.url)" &&
1151 remote_fetch="$(git -C one config remote.origin.fetch)" &&
1152 cmdline_setup="\"$remote_url\" \"$remote_fetch\""
1153 '
1154 fi
1155
1156 if test "$mode" = 'link'
1157 then
1158 new_cmdline=""
1159
1160 if test "$cmdline" = ""
1161 then
1162 new_cmdline=$cmdline_setup
1163 else
1164 new_cmdline=$(perl -e '
1165 my ($cmdline, $url) = @ARGV;
1166 $cmdline =~ s[origin(?!/)][quotemeta($url)]ge;
1167 print $cmdline;
1168 ' -- "$cmdline" "$remote_url")
1169 fi
1170
1171 if test "$fetch_prune_tags" = 'true' ||
1172 test "$remote_origin_prune_tags" = 'true'
1173 then
1174 if ! printf '%s' "$cmdline\n" | grep -q refs/remotes/origin/
1175 then
1176 new_cmdline="$new_cmdline refs/tags/*:refs/tags/*"
1177 fi
1178 fi
1179
1180 cmdline="$new_cmdline"
1181 fi
1182
1183 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" '
1184 # make sure a newbranch is there in . and also in one
1185 git branch -f newbranch &&
1186 git tag -f newtag &&
1187 (
1188 cd one &&
1189 test_unconfig fetch.prune &&
1190 test_unconfig fetch.pruneTags &&
1191 test_unconfig remote.origin.prune &&
1192 test_unconfig remote.origin.pruneTags &&
1193 git fetch '"$cmdline_setup"' &&
1194 git rev-parse --verify refs/remotes/origin/newbranch &&
1195 git rev-parse --verify refs/tags/newtag
1196 ) &&
1197
1198 # now remove them
1199 git branch -d newbranch &&
1200 git tag -d newtag &&
1201
1202 # then test
1203 (
1204 cd one &&
1205 git_fetch_c="" &&
1206 set_config_tristate fetch.prune $fetch_prune &&
1207 set_config_tristate fetch.pruneTags $fetch_prune_tags &&
1208 set_config_tristate remote.origin.prune $remote_origin_prune &&
1209 set_config_tristate remote.origin.pruneTags $remote_origin_prune_tags &&
1210
1211 if test "$mode" != "link"
1212 then
1213 git_fetch_c=""
1214 fi &&
1215 git$git_fetch_c fetch '"$cmdline"' &&
1216 case "$expected_branch" in
1217 pruned)
1218 test_must_fail git rev-parse --verify refs/remotes/origin/newbranch
1219 ;;
1220 kept)
1221 git rev-parse --verify refs/remotes/origin/newbranch
1222 ;;
1223 esac &&
1224 case "$expected_tag" in
1225 pruned)
1226 test_must_fail git rev-parse --verify refs/tags/newtag
1227 ;;
1228 kept)
1229 git rev-parse --verify refs/tags/newtag
1230 ;;
1231 esac
1232 )
1233 '
1234 }
1235
1236 # $1 config: fetch.prune
1237 # $2 config: remote.<name>.prune
1238 # $3 config: fetch.pruneTags
1239 # $4 config: remote.<name>.pruneTags
1240 # $5 expect: branch to be pruned?
1241 # $6 expect: tag to be pruned?
1242 # $7 git-fetch $cmdline:
1243 #
1244 # $1 $2 $3 $4 $5 $6 $7
1245 test_configured_prune unset unset unset unset kept kept ""
1246 test_configured_prune unset unset unset unset kept kept "--no-prune"
1247 test_configured_prune unset unset unset unset pruned kept "--prune"
1248 test_configured_prune unset unset unset unset kept pruned \
1249 "--prune origin refs/tags/*:refs/tags/*"
1250 test_configured_prune unset unset unset unset pruned pruned \
1251 "--prune origin refs/tags/*:refs/tags/* +refs/heads/*:refs/remotes/origin/*"
1252
1253 test_configured_prune false unset unset unset kept kept ""
1254 test_configured_prune false unset unset unset kept kept "--no-prune"
1255 test_configured_prune false unset unset unset pruned kept "--prune"
1256
1257 test_configured_prune true unset unset unset pruned kept ""
1258 test_configured_prune true unset unset unset pruned kept "--prune"
1259 test_configured_prune true unset unset unset kept kept "--no-prune"
1260
1261 test_configured_prune unset false unset unset kept kept ""
1262 test_configured_prune unset false unset unset kept kept "--no-prune"
1263 test_configured_prune unset false unset unset pruned kept "--prune"
1264
1265 test_configured_prune false false unset unset kept kept ""
1266 test_configured_prune false false unset unset kept kept "--no-prune"
1267 test_configured_prune false false unset unset pruned kept "--prune"
1268 test_configured_prune false false unset unset kept pruned \
1269 "--prune origin refs/tags/*:refs/tags/*"
1270 test_configured_prune false false unset unset pruned pruned \
1271 "--prune origin refs/tags/*:refs/tags/* +refs/heads/*:refs/remotes/origin/*"
1272
1273 test_configured_prune true false unset unset kept kept ""
1274 test_configured_prune true false unset unset pruned kept "--prune"
1275 test_configured_prune true false unset unset kept kept "--no-prune"
1276
1277 test_configured_prune unset true unset unset pruned kept ""
1278 test_configured_prune unset true unset unset kept kept "--no-prune"
1279 test_configured_prune unset true unset unset pruned kept "--prune"
1280
1281 test_configured_prune false true unset unset pruned kept ""
1282 test_configured_prune false true unset unset kept kept "--no-prune"
1283 test_configured_prune false true unset unset pruned kept "--prune"
1284
1285 test_configured_prune true true unset unset pruned kept ""
1286 test_configured_prune true true unset unset pruned kept "--prune"
1287 test_configured_prune true true unset unset kept kept "--no-prune"
1288 test_configured_prune true true unset unset kept pruned \
1289 "--prune origin refs/tags/*:refs/tags/*"
1290 test_configured_prune true true unset unset pruned pruned \
1291 "--prune origin refs/tags/*:refs/tags/* +refs/heads/*:refs/remotes/origin/*"
1292
1293 # --prune-tags on its own does nothing, needs --prune as well, same
1294 # for fetch.pruneTags without fetch.prune
1295 test_configured_prune unset unset unset unset kept kept "--prune-tags"
1296 test_configured_prune unset unset true unset kept kept ""
1297 test_configured_prune unset unset unset true kept kept ""
1298
1299 # These will prune the tags
1300 test_configured_prune unset unset unset unset pruned pruned "--prune --prune-tags"
1301 test_configured_prune true unset true unset pruned pruned ""
1302 test_configured_prune unset true unset true pruned pruned ""
1303
1304 # remote.<name>.pruneTags overrides fetch.pruneTags, just like
1305 # remote.<name>.prune overrides fetch.prune if set.
1306 test_configured_prune true unset true unset pruned pruned ""
1307 test_configured_prune false true false true pruned pruned ""
1308 test_configured_prune true false true false kept kept ""
1309
1310 # When --prune-tags is supplied it's ignored if an explicit refspec is
1311 # given, same for the configuration options.
1312 test_configured_prune unset unset unset unset pruned kept \
1313 "--prune --prune-tags origin +refs/heads/*:refs/remotes/origin/*"
1314 test_configured_prune unset unset true unset pruned kept \
1315 "--prune origin +refs/heads/*:refs/remotes/origin/*"
1316 test_configured_prune unset unset unset true pruned kept \
1317 "--prune origin +refs/heads/*:refs/remotes/origin/*"
1318
1319 # Pruning that also takes place if a file:// url replaces a named
1320 # remote. However, because there's no implicit
1321 # +refs/heads/*:refs/remotes/origin/* refspec and supplying it on the
1322 # command-line negates --prune-tags, the branches will not be pruned.
1323 test_configured_prune_type unset unset unset unset kept kept "origin --prune-tags" "name"
1324 test_configured_prune_type unset unset unset unset kept kept "origin --prune-tags" "link"
1325 test_configured_prune_type unset unset unset unset pruned pruned "origin --prune --prune-tags" "name"
1326 test_configured_prune_type unset unset unset unset kept pruned "origin --prune --prune-tags" "link"
1327 test_configured_prune_type unset unset unset unset pruned pruned "--prune --prune-tags origin" "name"
1328 test_configured_prune_type unset unset unset unset kept pruned "--prune --prune-tags origin" "link"
1329 test_configured_prune_type unset unset true unset pruned pruned "--prune origin" "name"
1330 test_configured_prune_type unset unset true unset kept pruned "--prune origin" "link"
1331 test_configured_prune_type unset unset unset true pruned pruned "--prune origin" "name"
1332 test_configured_prune_type unset unset unset true kept pruned "--prune origin" "link"
1333 test_configured_prune_type true unset true unset pruned pruned "origin" "name"
1334 test_configured_prune_type true unset true unset kept pruned "origin" "link"
1335 test_configured_prune_type unset true true unset pruned pruned "origin" "name"
1336 test_configured_prune_type unset true true unset kept pruned "origin" "link"
1337 test_configured_prune_type unset true unset true pruned pruned "origin" "name"
1338 test_configured_prune_type unset true unset true kept pruned "origin" "link"
1339
1340 # When all remote.origin.fetch settings are deleted a --prune
1341 # --prune-tags still implicitly supplies refs/tags/*:refs/tags/* so
1342 # tags, but not tracking branches, will be deleted.
1343 test_expect_success 'remove remote.origin.fetch "one"' '
1344 (
1345 cd one &&
1346 git config --unset-all remote.origin.fetch
1347 )
1348 '
1349 test_configured_prune_type unset unset unset unset kept pruned "origin --prune --prune-tags" "name"
1350 test_configured_prune_type unset unset unset unset kept pruned "origin --prune --prune-tags" "link"
1351
1352 test_expect_success 'all boundary commits are excluded' '
1353 test_commit base &&
1354 test_commit oneside &&
1355 git checkout HEAD^ &&
1356 test_commit otherside &&
1357 git checkout main &&
1358 test_tick &&
1359 git merge otherside &&
1360 ad=$(git log --no-walk --format=%ad HEAD) &&
1361
1362 # If the a different name hash function is used here, then no delta
1363 # pair is found and the bundle does not expand to three objects
1364 # when fixing the thin object.
1365 GIT_TEST_NAME_HASH_VERSION=1 \
1366 git bundle create twoside-boundary.bdl main --since="$ad" &&
1367 test_bundle_object_count --thin twoside-boundary.bdl 3
1368 '
1369
1370 test_expect_success 'fetch --prune prints the remotes url' '
1371 git branch goodbye &&
1372 git clone . only-prunes &&
1373 git branch -D goodbye &&
1374 (
1375 cd only-prunes &&
1376 git fetch --prune origin 2>&1 | head -n1 >../actual
1377 ) &&
1378 echo "From $(pwd)/." >expect &&
1379 test_cmp expect actual
1380 '
1381
1382 test_expect_success 'branchname D/F conflict resolved by --prune' '
1383 git branch dir/file &&
1384 git clone . prune-df-conflict &&
1385 git branch -D dir/file &&
1386 git branch dir &&
1387 (
1388 cd prune-df-conflict &&
1389 git fetch --prune &&
1390 git rev-parse origin/dir >../actual
1391 ) &&
1392 git rev-parse dir >expect &&
1393 test_cmp expect actual
1394 '
1395
1396 test_expect_success 'branchname D/F conflict rejected with targeted error message' '
1397 git clone . df-conflict-error &&
1398 git branch dir_conflict &&
1399 (
1400 cd df-conflict-error &&
1401 git update-ref refs/remotes/origin/dir_conflict/file HEAD &&
1402 test_must_fail git fetch 2>err &&
1403 test_grep "error: some local refs could not be updated; try running" err &&
1404 test_grep " ${SQ}git remote prune origin${SQ} to remove any old, conflicting branches" err &&
1405 git pack-refs --all &&
1406 test_must_fail git fetch 2>err-packed &&
1407 test_grep "error: some local refs could not be updated; try running" err-packed &&
1408 test_grep " ${SQ}git remote prune origin${SQ} to remove any old, conflicting branches" err-packed
1409 )
1410 '
1411
1412 test_expect_success 'fetching a one-level ref works' '
1413 test_commit extra &&
1414 git reset --hard HEAD^ &&
1415 git update-ref refs/foo extra &&
1416 git init one-level &&
1417 (
1418 cd one-level &&
1419 git fetch .. HEAD refs/foo
1420 )
1421 '
1422
1423 test_expect_success 'fetching with auto-gc does not lock up' '
1424 write_script askyesno <<-\EOF &&
1425 echo "$*" &&
1426 false
1427 EOF
1428 git clone "file://$PWD" auto-gc &&
1429 test_commit test2 &&
1430 (
1431 cd auto-gc &&
1432 git config fetch.unpackLimit 1 &&
1433 git config gc.autoPackLimit 1 &&
1434 git config gc.autoDetach false &&
1435 git config maintenance.strategy gc &&
1436 GIT_ASK_YESNO="$TRASH_DIRECTORY/askyesno" git fetch --verbose >fetch.out 2>&1 &&
1437 test_grep "Auto packing the repository" fetch.out &&
1438 test_grep ! "Should I try again" fetch.out
1439 )
1440 '
1441
1442 for section in fetch transfer
1443 do
1444 test_expect_success "$section.hideRefs affects connectivity check" '
1445 GIT_TRACE="$PWD"/trace git -c $section.hideRefs=refs -c \
1446 $section.hideRefs="!refs/tags/" fetch &&
1447 test_grep "git rev-list .*--exclude-hidden=fetch" trace
1448 '
1449 done
1450
1451 test_expect_success 'prepare source branch' '
1452 echo one >onebranch &&
1453 git checkout --orphan onebranch &&
1454 git rm --cached -r . &&
1455 git add onebranch &&
1456 git commit -m onebranch &&
1457 git rev-list --objects onebranch -- >actual &&
1458 # 3 objects should be created, at least ...
1459 test 3 -le $(wc -l <actual)
1460 '
1461
1462 validate_store_type () {
1463 git -C dest count-objects -v >actual &&
1464 case "$store_type" in
1465 packed)
1466 grep "^count: 0$" actual ;;
1467 loose)
1468 grep "^packs: 0$" actual ;;
1469 esac || {
1470 echo "store_type is $store_type"
1471 cat actual
1472 false
1473 }
1474 }
1475
1476 test_unpack_limit () {
1477 store_type=$1
1478
1479 case "$store_type" in
1480 packed) fetch_limit=1 transfer_limit=10000 ;;
1481 loose) fetch_limit=10000 transfer_limit=1 ;;
1482 esac
1483
1484 test_expect_success "fetch trumps transfer limit" '
1485 rm -fr dest &&
1486 git --bare init dest &&
1487 git -C dest config fetch.unpacklimit $fetch_limit &&
1488 git -C dest config transfer.unpacklimit $transfer_limit &&
1489 git -C dest fetch .. onebranch &&
1490 validate_store_type
1491 '
1492 }
1493
1494 test_unpack_limit packed
1495 test_unpack_limit loose
1496
1497 setup_negotiation_tip () {
1498 SERVER="$1"
1499 URL="$2"
1500 USE_PROTOCOL_V2="$3"
1501
1502 rm -rf "$SERVER" client trace &&
1503 git init -b main "$SERVER" &&
1504 test_commit -C "$SERVER" alpha_1 &&
1505 test_commit -C "$SERVER" alpha_2 &&
1506 git -C "$SERVER" checkout --orphan beta &&
1507 test_commit -C "$SERVER" beta_1 &&
1508 test_commit -C "$SERVER" beta_2 &&
1509
1510 git clone "$URL" client &&
1511
1512 if test "$USE_PROTOCOL_V2" -eq 1
1513 then
1514 git -C "$SERVER" config protocol.version 2 &&
1515 git -C client config protocol.version 2
1516 fi &&
1517
1518 test_commit -C "$SERVER" beta_s &&
1519 git -C "$SERVER" checkout main &&
1520 test_commit -C "$SERVER" alpha_s &&
1521 git -C "$SERVER" tag -d alpha_1 alpha_2 beta_1 beta_2
1522 }
1523
1524 check_negotiation_tip () {
1525 # Ensure that {alpha,beta}_1 are sent as "have", but not {alpha_beta}_2
1526 ALPHA_1=$(git -C client rev-parse alpha_1) &&
1527 grep "fetch> have $ALPHA_1" trace &&
1528 BETA_1=$(git -C client rev-parse beta_1) &&
1529 grep "fetch> have $BETA_1" trace &&
1530 ALPHA_2=$(git -C client rev-parse alpha_2) &&
1531 ! grep "fetch> have $ALPHA_2" trace &&
1532 BETA_2=$(git -C client rev-parse beta_2) &&
1533 ! grep "fetch> have $BETA_2" trace
1534 }
1535
1536 test_expect_success '--negotiation-tip limits "have" lines sent' '
1537 setup_negotiation_tip server server 0 &&
1538 GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch \
1539 --negotiation-tip=alpha_1 --negotiation-tip=beta_1 \
1540 origin alpha_s beta_s &&
1541 check_negotiation_tip
1542 '
1543
1544 test_expect_success '--negotiation-tip understands globs' '
1545 setup_negotiation_tip server server 0 &&
1546 GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch \
1547 --negotiation-tip=*_1 \
1548 origin alpha_s beta_s &&
1549 check_negotiation_tip
1550 '
1551
1552 test_expect_success '--negotiation-tip understands abbreviated SHA-1' '
1553 setup_negotiation_tip server server 0 &&
1554 GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch \
1555 --negotiation-tip=$(git -C client rev-parse --short alpha_1) \
1556 --negotiation-tip=$(git -C client rev-parse --short beta_1) \
1557 origin alpha_s beta_s &&
1558 check_negotiation_tip
1559 '
1560
1561 test_expect_success '--negotiation-tip rejects missing OIDs' '
1562 setup_negotiation_tip server server 0 &&
1563 test_must_fail git -C client fetch \
1564 --negotiation-tip=alpha_1 \
1565 --negotiation-tip=$(test_oid zero) \
1566 origin alpha_s beta_s 2>err &&
1567 cat >fatal-expect <<-EOF &&
1568 fatal: the object $(test_oid zero) does not exist
1569 EOF
1570 grep fatal: err >fatal-actual &&
1571 test_cmp fatal-expect fatal-actual
1572 '
1573
1574 test_expect_success '--negotiation-tip ignores missing refs and invalid hashes' '
1575 setup_negotiation_tip server server 0 &&
1576 GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch \
1577 --negotiation-tip=alpha_1 --negotiation-tip=beta_1 \
1578 --negotiation-tip=no-such-ref \
1579 --negotiation-tip=invalid-hash \
1580 origin alpha_s beta_s &&
1581 check_negotiation_tip
1582 '
1583
1584 test_expect_success '--negotiation-restrict limits "have" lines sent' '
1585 setup_negotiation_tip server server 0 &&
1586 GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch \
1587 --negotiation-restrict=alpha_1 --negotiation-restrict=beta_1 \
1588 origin alpha_s beta_s &&
1589 check_negotiation_tip
1590 '
1591
1592 test_expect_success '--negotiation-restrict understands globs' '
1593 setup_negotiation_tip server server 0 &&
1594 GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch \
1595 --negotiation-restrict=*_1 \
1596 origin alpha_s beta_s &&
1597 check_negotiation_tip
1598 '
1599
1600 test_expect_success '--negotiation-restrict and --negotiation-tip can be mixed' '
1601 setup_negotiation_tip server server 0 &&
1602 GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch \
1603 --negotiation-restrict=alpha_1 \
1604 --negotiation-tip=beta_1 \
1605 origin alpha_s beta_s &&
1606 check_negotiation_tip
1607 '
1608
1609 test_expect_success 'remote.<name>.negotiationRestrict used as default' '
1610 setup_negotiation_tip server server 0 &&
1611
1612 # test the reset of the list on an empty value
1613 git -C client config --add remote.origin.negotiationRestrict alpha_2 &&
1614 git -C client config --add remote.origin.negotiationRestrict "" &&
1615 git -C client config --add remote.origin.negotiationRestrict alpha_1 &&
1616 git -C client config --add remote.origin.negotiationRestrict beta_1 &&
1617 GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch \
1618 origin alpha_s beta_s &&
1619 check_negotiation_tip
1620 '
1621
1622 test_expect_success 'CLI --negotiation-restrict overrides remote config' '
1623 setup_negotiation_tip server server 0 &&
1624 git -C client config --add remote.origin.negotiationRestrict alpha_1 &&
1625 git -C client config --add remote.origin.negotiationRestrict beta_1 &&
1626 ALPHA_1=$(git -C client rev-parse alpha_1) &&
1627 GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch \
1628 --negotiation-restrict=alpha_1 \
1629 origin alpha_s beta_s &&
1630 test_grep "fetch> have $ALPHA_1" trace &&
1631 BETA_1=$(git -C client rev-parse beta_1) &&
1632 test_grep ! "fetch> have $BETA_1" trace
1633 '
1634
1635 test_expect_success '--negotiation-include includes configured refs as haves' '
1636 test_when_finished rm -f trace &&
1637 setup_negotiation_tip server server 0 &&
1638
1639 GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch \
1640 --negotiation-restrict=alpha_1 \
1641 --negotiation-include=refs/tags/beta_1 \
1642 origin alpha_s beta_s &&
1643
1644 ALPHA_1=$(git -C client rev-parse alpha_1) &&
1645 test_grep "fetch> have $ALPHA_1" trace &&
1646 BETA_1=$(git -C client rev-parse beta_1) &&
1647 test_grep "fetch> have $BETA_1" trace
1648 '
1649
1650 test_expect_success '--negotiation-include works with glob patterns' '
1651 test_when_finished rm -f trace &&
1652 setup_negotiation_tip server server 0 &&
1653
1654 GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch \
1655 --negotiation-restrict=alpha_1 \
1656 --negotiation-include="refs/tags/beta_*" \
1657 origin alpha_s beta_s &&
1658
1659 BETA_1=$(git -C client rev-parse beta_1) &&
1660 test_grep "fetch> have $BETA_1" trace &&
1661 BETA_2=$(git -C client rev-parse beta_2) &&
1662 test_grep "fetch> have $BETA_2" trace
1663 '
1664
1665 test_expect_success '--negotiation-include is additive with negotiation' '
1666 test_when_finished rm -f trace &&
1667 setup_negotiation_tip server server 0 &&
1668
1669 GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch \
1670 --negotiation-include=refs/tags/beta_1 \
1671 origin alpha_s beta_s &&
1672
1673 BETA_1=$(git -C client rev-parse beta_1) &&
1674 test_grep "fetch> have $BETA_1" trace
1675 '
1676
1677 test_expect_success '--negotiation-include ignores non-existent refs silently' '
1678 setup_negotiation_tip server server 0 &&
1679
1680 git -C client fetch --quiet \
1681 --negotiation-restrict=alpha_1 \
1682 --negotiation-include=refs/tags/nonexistent \
1683 origin alpha_s beta_s 2>err &&
1684 test_must_be_empty err
1685 '
1686
1687 test_expect_success '--negotiation-include avoids duplicates with negotiator' '
1688 test_when_finished rm -f trace &&
1689 setup_negotiation_tip server server 0 &&
1690
1691 ALPHA_1=$(git -C client rev-parse alpha_1) &&
1692 GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch \
1693 --negotiation-restrict=alpha_1 \
1694 --negotiation-include=refs/tags/alpha_1 \
1695 origin alpha_s beta_s &&
1696
1697 test_grep "fetch> have $ALPHA_1" trace >matches &&
1698 test_line_count = 1 matches
1699 '
1700
1701 test_expect_success 'remote.<name>.negotiationInclude used as default for --negotiation-include' '
1702 test_when_finished rm -f trace &&
1703 setup_negotiation_tip server server 0 &&
1704
1705 # test the reset of the list on an empty value
1706 git -C client config --add remote.origin.negotiationInclude refs/tags/alpha_1 &&
1707 git -C client config --add remote.origin.negotiationInclude "" &&
1708 git -C client config --add remote.origin.negotiationInclude refs/tags/beta_1 &&
1709 GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch \
1710 --negotiation-restrict=beta_2 \
1711 origin alpha_s beta_s &&
1712
1713 ALPHA_1=$(git -C client rev-parse alpha_1) &&
1714 test_grep ! "fetch> have $ALPHA_1" trace &&
1715 BETA_1=$(git -C client rev-parse beta_1) &&
1716 test_grep "fetch> have $BETA_1" trace
1717 '
1718
1719 test_expect_success 'remote.<name>.negotiationInclude works with glob patterns' '
1720 test_when_finished rm -f trace &&
1721 setup_negotiation_tip server server 0 &&
1722
1723 git -C client config --add remote.origin.negotiationInclude "refs/tags/beta_*" &&
1724 GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch \
1725 --negotiation-restrict=alpha_1 \
1726 origin alpha_s beta_s &&
1727
1728 BETA_1=$(git -C client rev-parse beta_1) &&
1729 test_grep "fetch> have $BETA_1" trace &&
1730 BETA_2=$(git -C client rev-parse beta_2) &&
1731 test_grep "fetch> have $BETA_2" trace
1732 '
1733
1734 test_expect_success 'CLI --negotiation-include overrides remote.<name>.negotiationInclude' '
1735 test_when_finished rm -f trace &&
1736 setup_negotiation_tip server server 0 &&
1737
1738 git -C client config --add remote.origin.negotiationInclude refs/tags/beta_2 &&
1739 GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch \
1740 --negotiation-restrict=alpha_1 \
1741 --negotiation-include=refs/tags/beta_1 \
1742 origin alpha_s beta_s &&
1743
1744 BETA_1=$(git -C client rev-parse beta_1) &&
1745 test_grep "fetch> have $BETA_1" trace &&
1746 BETA_2=$(git -C client rev-parse beta_2) &&
1747 test_grep ! "fetch> have $BETA_2" trace
1748 '
1749
1750 test_expect_success '--negotiation-include avoids duplicates with v0' '
1751 test_when_finished rm -f trace &&
1752 setup_negotiation_tip server server 0 &&
1753
1754 ALPHA_1=$(git -C client rev-parse alpha_1) &&
1755 GIT_TRACE_PACKET="$(pwd)/trace" git -C client \
1756 -c protocol.version=0 fetch \
1757 --negotiation-restrict=alpha_1 \
1758 --negotiation-include=refs/tags/alpha_1 \
1759 origin alpha_s beta_s &&
1760
1761 test_grep "fetch> have $ALPHA_1" trace >matches &&
1762 test_line_count = 1 matches
1763 '
1764
1765 test_expect_success SYMLINKS 'clone does not get confused by a D/F conflict' '
1766 git init df-conflict &&
1767 (
1768 cd df-conflict &&
1769 ln -s .git a &&
1770 git add a &&
1771 test_tick &&
1772 git commit -m symlink &&
1773 test_commit a- &&
1774 rm a &&
1775 mkdir -p a/hooks &&
1776 write_script a/hooks/post-checkout <<-EOF &&
1777 echo WHOOPSIE >&2
1778 echo whoopsie >"$TRASH_DIRECTORY"/whoops
1779 EOF
1780 git add a/hooks/post-checkout &&
1781 test_tick &&
1782 git commit -m post-checkout
1783 ) &&
1784 git clone df-conflict clone 2>err &&
1785 test_grep ! WHOOPS err &&
1786 test_path_is_missing whoops
1787 '
1788
1789 test_expect_success CASE_INSENSITIVE_FS,REFFILES 'existing references in a case insensitive filesystem' '
1790 test_when_finished rm -rf case_insensitive &&
1791 (
1792 git init --bare case_insensitive &&
1793 cd case_insensitive &&
1794 git remote add origin -- ../case_sensitive &&
1795 test_must_fail git fetch -f origin "refs/heads/*:refs/heads/*" 2>err &&
1796 test_grep "You${SQ}re on a case-insensitive filesystem" err &&
1797 git rev-parse refs/heads/main >expect &&
1798 git rev-parse refs/heads/branch1 >actual &&
1799 test_cmp expect actual
1800 )
1801 '
1802
1803 test_expect_success REFFILES 'existing reference lock in repo' '
1804 test_when_finished rm -rf base repo &&
1805 (
1806 git init --ref-format=reftable base &&
1807 cd base &&
1808 echo >file update &&
1809 git add . &&
1810 git commit -m "updated" &&
1811 git branch -M main &&
1812
1813 git update-ref refs/heads/foo @ &&
1814 git update-ref refs/heads/branch @ &&
1815 cd .. &&
1816
1817 git init --ref-format=files --bare repo &&
1818 cd repo &&
1819 git remote add origin ../base &&
1820 touch refs/heads/foo.lock &&
1821 test_must_fail git fetch -f origin "refs/heads/*:refs/heads/*" 2>err &&
1822 test_grep -e "error: cannot lock ref ${SQ}refs/heads/foo${SQ}: Unable to create" -e "refs/heads/foo.lock${SQ}: File exists." err &&
1823 git rev-parse refs/heads/main >expect &&
1824 git rev-parse refs/heads/branch >actual &&
1825 test_cmp expect actual
1826 )
1827 '
1828
1829 test_expect_success CASE_INSENSITIVE_FS,REFFILES 'F/D conflict on case insensitive filesystem' '
1830 test_when_finished rm -rf case_insensitive &&
1831 (
1832 git init --bare case_insensitive &&
1833 cd case_insensitive &&
1834 git remote add origin -- ../case_sensitive_fd &&
1835 test_must_fail git fetch -f origin "refs/heads/*:refs/heads/*" 2>err &&
1836 test_grep "cannot process ${SQ}refs/remotes/origin/foo${SQ} and ${SQ}refs/remotes/origin/foo/bar${SQ} at the same time" err &&
1837 git rev-parse refs/heads/main >expect &&
1838 git rev-parse refs/heads/foo/bar >actual &&
1839 test_cmp expect actual
1840 )
1841 '
1842
1843 test_expect_success CASE_INSENSITIVE_FS,REFFILES 'D/F conflict on case insensitive filesystem' '
1844 test_when_finished rm -rf case_insensitive &&
1845 (
1846 git init --bare case_insensitive &&
1847 cd case_insensitive &&
1848 git remote add origin -- ../case_sensitive_df &&
1849 test_must_fail git fetch -f origin "refs/heads/*:refs/heads/*" 2>err &&
1850 test_grep "cannot lock ref ${SQ}refs/remotes/origin/foo${SQ}: there is a non-empty directory ${SQ}./refs/remotes/origin/foo${SQ} blocking reference ${SQ}refs/remotes/origin/foo${SQ}" err &&
1851 git rev-parse refs/heads/main >expect &&
1852 git rev-parse refs/heads/Foo/bar >actual &&
1853 test_cmp expect actual
1854 )
1855 '
1856
1857 test_expect_success REFFILES 'D/F conflict on case sensitive filesystem with lock' '
1858 test_when_finished rm -rf base repo &&
1859 (
1860 git init --ref-format=reftable base &&
1861 cd base &&
1862 echo >file update &&
1863 git add . &&
1864 git commit -m "updated" &&
1865 git branch -M main &&
1866
1867 git update-ref refs/heads/foo @ &&
1868 git update-ref refs/heads/branch @ &&
1869 cd .. &&
1870
1871 git init --ref-format=files --bare repo &&
1872 cd repo &&
1873 git remote add origin ../base &&
1874 mkdir refs/heads/foo &&
1875 touch refs/heads/foo/random.lock &&
1876 test_must_fail git fetch origin "refs/heads/*:refs/heads/*" 2>err &&
1877 test_grep "some local refs could not be updated; try running" err &&
1878 git rev-parse refs/heads/main >expect &&
1879 git rev-parse refs/heads/branch >actual &&
1880 test_cmp expect actual
1881 )
1882 '
1883
1884 test_expect_success 'fetch --tags fetches existing tags' '
1885 test_when_finished rm -rf base repo &&
1886
1887 git init base &&
1888 git -C base commit --allow-empty -m "empty-commit" &&
1889
1890 git clone --bare base repo &&
1891
1892 git -C base tag tag-1 &&
1893 git -C repo for-each-ref >out &&
1894 test_grep ! "tag-1" out &&
1895 git -C repo fetch --tags &&
1896 git -C repo for-each-ref >out &&
1897 test_grep "tag-1" out
1898 '
1899
1900 test_expect_success 'fetch --tags fetches non-conflicting tags' '
1901 test_when_finished rm -rf base repo &&
1902
1903 git init base &&
1904 git -C base commit --allow-empty -m "empty-commit" &&
1905 git -C base tag tag-1 &&
1906
1907 git clone --bare base repo &&
1908
1909 git -C base tag tag-2 &&
1910 git -C repo for-each-ref >out &&
1911 test_grep ! "tag-2" out &&
1912
1913 git -C base commit --allow-empty -m "second empty-commit" &&
1914 git -C base tag -f tag-1 &&
1915
1916 test_must_fail git -C repo fetch --tags 2>out &&
1917 test_grep "tag-1 (would clobber existing tag)" out &&
1918 git -C repo for-each-ref >out &&
1919 test_grep "tag-2" out
1920 '
1921
1922 test_expect_success "backfill tags when providing a refspec" '
1923 test_when_finished rm -rf source target &&
1924
1925 git init source &&
1926 git -C source commit --allow-empty --message common &&
1927 git clone file://"$(pwd)"/source target &&
1928 (
1929 cd source &&
1930 test_commit history &&
1931 test_commit fetch-me
1932 ) &&
1933
1934 # The "history" tag is backfilled even though we requested
1935 # to only fetch HEAD
1936 git -C target fetch origin HEAD:branch &&
1937 git -C target tag -l >actual &&
1938 cat >expect <<-\EOF &&
1939 fetch-me
1940 history
1941 EOF
1942 test_cmp expect actual
1943 '
1944
1945 test_expect_success REFFILES "FETCH_HEAD is updated even if ref updates fail" '
1946 test_when_finished rm -rf base repo &&
1947
1948 git init base &&
1949 (
1950 cd base &&
1951 test_commit "updated" &&
1952
1953 git update-ref refs/heads/foo @ &&
1954 git update-ref refs/heads/branch @
1955 ) &&
1956
1957 git init --bare repo &&
1958 (
1959 cd repo &&
1960 rm -f FETCH_HEAD &&
1961 git remote add origin ../base &&
1962 >refs/heads/foo.lock &&
1963 test_must_fail git fetch -f origin "refs/heads/*:refs/heads/*" 2>err &&
1964 test_grep -e "error: cannot lock ref ${SQ}refs/heads/foo${SQ}: Unable to create" -e "refs/heads/foo.lock${SQ}: File exists." err &&
1965 test_grep "branch ${SQ}branch${SQ} of ../base" FETCH_HEAD &&
1966 test_grep "branch ${SQ}foo${SQ} of ../base" FETCH_HEAD
1967 )
1968 '
1969
1970 test_expect_success "upstream tracking info is added with --set-upstream" '
1971 test_when_finished rm -rf base repo &&
1972
1973 git init --initial-branch=main base &&
1974 test_commit -C base "updated" &&
1975
1976 git init --bare --initial-branch=main repo &&
1977 (
1978 cd repo &&
1979 git remote add origin ../base &&
1980 git fetch origin --set-upstream main &&
1981 git config get branch.main.remote >actual &&
1982 echo "origin" >expect &&
1983 test_cmp expect actual
1984 )
1985 '
1986
1987 test_expect_success REFFILES "upstream tracking info is added even with conflicts" '
1988 test_when_finished rm -rf base repo &&
1989
1990 git init --initial-branch=main base &&
1991 test_commit -C base "updated" &&
1992
1993 git init --bare --initial-branch=main repo &&
1994 (
1995 cd repo &&
1996 git remote add origin ../base &&
1997 test_must_fail git config get branch.main.remote &&
1998
1999 mkdir -p refs/remotes/origin &&
2000 >refs/remotes/origin/main.lock &&
2001 test_must_fail git fetch origin --set-upstream main &&
2002 git config get branch.main.remote >actual &&
2003 echo "origin" >expect &&
2004 test_cmp expect actual
2005 )
2006 '
2007
2008 test_expect_success REFFILES "HEAD is updated even with conflicts" '
2009 test_when_finished rm -rf base repo &&
2010
2011 git init base &&
2012 (
2013 cd base &&
2014 test_commit "updated" &&
2015
2016 git update-ref refs/heads/foo @ &&
2017 git update-ref refs/heads/branch @
2018 ) &&
2019
2020 git init --bare repo &&
2021 (
2022 cd repo &&
2023 git remote add origin ../base &&
2024
2025 test_path_is_missing refs/remotes/origin/HEAD &&
2026 mkdir -p refs/remotes/origin &&
2027 >refs/remotes/origin/branch.lock &&
2028 test_must_fail git fetch origin &&
2029 test -f refs/remotes/origin/HEAD
2030 )
2031 '
2032
2033 . "$TEST_DIRECTORY"/lib-httpd.sh
2034 start_httpd
2035
2036 test_expect_success '--negotiation-tip limits "have" lines sent with HTTP protocol v2' '
2037 setup_negotiation_tip "$HTTPD_DOCUMENT_ROOT_PATH/server" \
2038 "$HTTPD_URL/smart/server" 1 &&
2039 GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch \
2040 --negotiation-tip=alpha_1 --negotiation-tip=beta_1 \
2041 origin alpha_s beta_s &&
2042 check_negotiation_tip
2043 '
2044
2045 # DO NOT add non-httpd-specific tests here, because the last part of this
2046 # test script is only executed when httpd is available and enabled.
2047
2048 test_done