git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v2 1/2] partial-clone: demonstrate bugs in partial fetch

From
Derrick Stolee via GitGitGadget <gitgitgadget@gmail.com>
Date
Feb 21, 2020, 21:47 UTC
Message-ID
<04965a8c7a48b2fbb5049b640487015fdd7bbd22.1582321648.git.gitgitgadget@gmail.com>
In-Reply-To
<pull.556.v2.git.1582321648.gitgitgadget@gmail.com>
From: Derrick Stolee <dstolee@microsoft.com>

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 6462d5eb9a (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 <dstolee@microsoft.com>
---
 t/t5616-partial-clone.sh | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)
diff --git a/t/t5616-partial-clone.sh b/t/t5616-partial-clone.sh
index fea56cda6d3..022f1018ace 100755
--- a/t/t5616-partial-clone.sh
+++ b/t/t5616-partial-clone.sh
@@ -374,6 +374,37 @@ test_expect_success 'fetch lazy-fetches only to resolve deltas, protocol v2' '
 	grep "want $(cat hash)" trace
 '
 
+# The following two tests must be in this order, or else
+# the first will not fail. It is important that the srv.bare
+# repository did not have tags during clone, but has tags
+# in the fetch.
+
+test_expect_failure 'verify fetch succeeds when asking for new tags' '
+	git clone --filter=blob:none "file://$(pwd)/srv.bare" tag-test &&
+	for i in I J K
+	do
+		test_commit -C src $i &&
+		git -C src branch $i || return 1
+	done &&
+	git -C srv.bare fetch --tags origin +refs/heads/*:refs/heads/* &&
+	git -C tag-test -c protocol.version=2 fetch --tags origin
+'
+
+test_expect_failure 'verify fetch downloads only one pack when updating refs' '
+	git clone --filter=blob:none "file://$(pwd)/srv.bare" pack-test &&
+	ls pack-test/.git/objects/pack/*pack >pack-list &&
+	test_line_count = 2 pack-list &&
+	for i in A B C
+	do
+		test_commit -C src $i &&
+		git -C src branch $i || return 1
+	done &&
+	git -C srv.bare fetch origin +refs/heads/*:refs/heads/* &&
+	git -C pack-test fetch origin &&
+	ls pack-test/.git/objects/pack/*pack >pack-list &&
+	test_line_count = 3 pack-list
+'
+
 . "$TEST_DIRECTORY"/lib-httpd.sh
 start_httpd
 
-- 
gitgitgadget
Previous: Derrick Stolee via GitGitGadgetNext: Derrick Stolee via GitGitGadget
Message 13 of 15 in “Document two partial clone bugs, fix one”
  1. 0/2 Document two partial clone bugs, fix oneDerrick Stolee via GitGitGadget, Feb 19, 2020
  2. 1/2 partial-clone: demonstrate bugs in partial fetchDerrick Stolee via GitGitGadget, Feb 19, 2020
  3. Eric SunshineFeb 19, 2020
  4. Derrick StoleeFeb 19, 2020
  5. Junio C HamanoFeb 19, 2020
  6. Eric SunshineFeb 19, 2020
  7. Junio C HamanoFeb 19, 2020
  8. Derrick StoleeFeb 19, 2020
  9. 2/2 partial-clone: avoid fetching when looking for objectsDerrick Stolee via GitGitGadget, Feb 19, 2020
  10. Jonathan TanFeb 19, 2020
  11. Derrick StoleeFeb 19, 2020
  12. 0/2 Document two partial clone bugs, fix oneDerrick Stolee via GitGitGadget, Feb 21, 2020
  13. 1/2 partial-clone: demonstrate bugs in partial fetchDerrick Stolee via GitGitGadget, Feb 21, 2020
  14. 2/2 partial-clone: avoid fetching when looking for objectsDerrick Stolee via GitGitGadget, Feb 21, 2020
  15. Junio C HamanoFeb 22, 2020

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.