Skip to content

Commit d0badf8

Browse files
derrickstoleegitster
authored andcommitted
partial-clone: demonstrate bugs in partial fetch
While testing partial clone, I noticed some odd behavior. I was testing a way of running 'git init', followed by manually configuring the remote for partial clone, and then running 'git fetch'. Astonishingly, I saw the 'git fetch' process start asking the server for multiple rounds of pack-file downloads! When tweaking the situation a little more, I discovered that I could cause the remote to hang up with an error. Add two tests that demonstrate these two issues. In the first test, we find that when fetching with blob filters from a repository that previously did not have any tags, the 'git fetch --tags origin' command fails because the server sends "multiple filter-specs cannot be combined". This only happens when using protocol v2. In the second test, we see that a 'git fetch origin' request with several ref updates results in multiple pack-file downloads. This must be due to Git trying to fault-in the objects pointed by the refs. What makes this matter particularly nasty is that this goes through the do_oid_object_info_extended() method, so there are no "haves" in the negotiation. This leads the remote to send every reachable commit and tree from each new ref, providing a quadratic amount of data transfer! This test is fixed if we revert 6462d5e (fetch: remove fetch_if_missing=0, 2019-11-05), but that revert causes other test failures. The real fix will need more care. The tests are ordered in this way because if I swap the test order the tag test will succeed instead of fail. I believe this is because somehow we need the srv.bare repo to not have any tags when we clone, but then have tags in our next fetch. Signed-off-by: Derrick Stolee <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent d0654dc commit d0badf8

File tree

1 file changed

+31
-0
lines changed

1 file changed

+31
-0
lines changed

t/t5616-partial-clone.sh

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,37 @@ test_expect_success 'fetch lazy-fetches only to resolve deltas, protocol v2' '
374374
grep "want $(cat hash)" trace
375375
'
376376

377+
# The following two tests must be in this order, or else
378+
# the first will not fail. It is important that the srv.bare
379+
# repository did not have tags during clone, but has tags
380+
# in the fetch.
381+
382+
test_expect_failure 'verify fetch succeeds when asking for new tags' '
383+
git clone --filter=blob:none "file://$(pwd)/srv.bare" tag-test &&
384+
for i in I J K
385+
do
386+
test_commit -C src $i &&
387+
git -C src branch $i || return 1
388+
done &&
389+
git -C srv.bare fetch --tags origin +refs/heads/*:refs/heads/* &&
390+
git -C tag-test -c protocol.version=2 fetch --tags origin
391+
'
392+
393+
test_expect_failure 'verify fetch downloads only one pack when updating refs' '
394+
git clone --filter=blob:none "file://$(pwd)/srv.bare" pack-test &&
395+
ls pack-test/.git/objects/pack/*pack >pack-list &&
396+
test_line_count = 2 pack-list &&
397+
for i in A B C
398+
do
399+
test_commit -C src $i &&
400+
git -C src branch $i || return 1
401+
done &&
402+
git -C srv.bare fetch origin +refs/heads/*:refs/heads/* &&
403+
git -C pack-test fetch origin &&
404+
ls pack-test/.git/objects/pack/*pack >pack-list &&
405+
test_line_count = 3 pack-list
406+
'
407+
377408
. "$TEST_DIRECTORY"/lib-httpd.sh
378409
start_httpd
379410

0 commit comments

Comments
 (0)