{"thread":{"id":"64674","subject":"[PATCH 0/2] Fix shallow clone with ref-in-want enabled","startedAt":"2025-12-24T00:36:16Z","lastAt":"2026-01-05T13:00:55Z","messageCount":4,"participants":["Matthew Dodd","Patrick Steinhardt"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"532672","messageId":"20251224003504.52660-1-mats.dodd12@gmail.com","threadId":"64674","inReplyTo":null,"subject":"[PATCH 0/2] Fix shallow clone with ref-in-want enabled","fromName":"Matthew Dodd","fromEmail":"mats.dodd12@gmail.com","sentAt":"2025-12-24T00:35:02Z","receivedAt":"2025-12-24T00:36:16Z","isPatch":true,"sender":{"key":"mats.dodd12@gmail.com","avatar":null},"body":"From: Mats-Dodd <mats.dodd12@gmail.com>\n\nThe ref-in-want feature (uploadpack.allowRefInWant) has been broken with\nshallow clones since it was introduced in 516e2b76bdc (upload-pack:\nimplement ref-in-want, 2018-06-27). When enabled, shallow clones fail\nwith:\n\n    fatal: expected 'packfile', received 'shallow-info'\n\nThe server sends protocol v2 sections in the wrong order, violating the\nspecification in Documentation/gitprotocol-v2.adoc and client expectations\nin fetch-pack.c.\n\nThis series:\n1. Fixes the section ordering in upload-pack.c (swap two lines)\n2. Adds a regression test for shallow clone + ref-in-want\n\nMats-Dodd (2):\n  upload-pack: send shallow-info before wanted-refs in protocol v2\n  t5703: add test for shallow fetch with ref-in-want\n\n t/t5703-upload-pack-ref-in-want.sh | 9 +++++++++\n upload-pack.c                      | 2 +-\n 2 files changed, 10 insertions(+), 1 deletion(-)\n\n\nbase-commit: 9a2fb147f2c61d0cab52c883e7e26f5b7948e3ed\n-- \n2.47.0\n\n"},{"id":"532673","messageId":"20251224003504.52660-2-mats.dodd12@gmail.com","threadId":"64674","inReplyTo":"20251224003504.52660-1-mats.dodd12@gmail.com","subject":"[PATCH 1/2] upload-pack: send shallow-info before wanted-refs in protocol v2","fromName":"Matthew Dodd","fromEmail":"mats.dodd12@gmail.com","sentAt":"2025-12-24T00:35:03Z","receivedAt":"2025-12-24T00:36:17Z","isPatch":true,"sender":{"key":"mats.dodd12@gmail.com","avatar":null},"body":"From: Mats-Dodd <mats.dodd12@gmail.com>\n\nThe protocol v2 specification (Documentation/gitprotocol-v2.adoc) defines\nthe ordering of optional sections in the fetch response as:\n\n    [acknowledgments delim-pkt] [shallow-info delim-pkt]\n    [wanted-refs delim-pkt] [packfile-uris delim-pkt]\n    packfile flush-pkt\n\nHowever, since the ref-in-want feature was introduced in 516e2b76bdc\n(upload-pack: implement ref-in-want, 2018-06-27), the server sends\nwanted-refs before shallow-info. This violates the specification and\nbreaks the client (fetch-pack.c), which expects shallow-info first.\n\nWhen a client performs a shallow clone/fetch against a server with\nuploadpack.allowRefInWant=true, the client receives sections in the\nwrong order and fails with:\n\n    fatal: expected 'packfile', received 'shallow-info'\n\nFix by swapping the order of send_shallow_info() and\nsend_wanted_ref_info() to match both the protocol specification and\nclient expectations.\n\nSigned-off-by: Mats-Dodd <mats.dodd12@gmail.com>\n---\n upload-pack.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/upload-pack.c b/upload-pack.c\nindex 1e87ae9559..029ca93e69 100644\n--- a/upload-pack.c\n+++ b/upload-pack.c\n@@ -1830,8 +1830,8 @@ int upload_pack_v2(struct repository *r, struct packet_reader *request)\n \t\t\t\tstate = UPLOAD_DONE;\n \t\t\tbreak;\n \t\tcase UPLOAD_SEND_PACK:\n-\t\t\tsend_wanted_ref_info(&data);\n \t\t\tsend_shallow_info(&data);\n+\t\t\tsend_wanted_ref_info(&data);\n \n \t\t\tif (data.uri_protocols.nr) {\n \t\t\t\tcreate_pack_file(&data, &data.uri_protocols);\n-- \n2.47.0\n\n"},{"id":"532674","messageId":"20251224003504.52660-3-mats.dodd12@gmail.com","threadId":"64674","inReplyTo":"20251224003504.52660-1-mats.dodd12@gmail.com","subject":"[PATCH 2/2] t5703: add test for shallow fetch with ref-in-want","fromName":"Matthew Dodd","fromEmail":"mats.dodd12@gmail.com","sentAt":"2025-12-24T00:35:04Z","receivedAt":"2025-12-24T00:36:19Z","isPatch":true,"sender":{"key":"mats.dodd12@gmail.com","avatar":null},"body":"From: Mats-Dodd <mats.dodd12@gmail.com>\n\nAdd a regression test for shallow clone operations when the server has\nuploadpack.allowRefInWant enabled. Before the previous commit, this\noperation would fail with:\n\n    fatal: expected 'packfile', received 'shallow-info'\n\nThis was due to the server sending protocol v2 sections in the wrong\norder. The test ensures this scenario continues to work.\n\nSigned-off-by: Mats-Dodd <mats.dodd12@gmail.com>\n---\n t/t5703-upload-pack-ref-in-want.sh | 9 +++++++++\n 1 file changed, 9 insertions(+)\n\ndiff --git a/t/t5703-upload-pack-ref-in-want.sh b/t/t5703-upload-pack-ref-in-want.sh\nindex 249137b467..21f4049eb4 100755\n--- a/t/t5703-upload-pack-ref-in-want.sh\n+++ b/t/t5703-upload-pack-ref-in-want.sh\n@@ -256,6 +256,15 @@ test_expect_success 'fetching multiple refs' '\n \tgrep \"want-ref refs/heads/baz\" log\n '\n \n+test_expect_success 'fetching with ref-in-want and shallow' '\n+\trm -rf local &&\n+\tgit -c protocol.version=2 clone --depth=1 \"file://$REPO\" local &&\n+\n+\tgit -C \"$REPO\" rev-parse main >expected &&\n+\tgit -C local rev-parse refs/remotes/origin/main >actual &&\n+\ttest_cmp expected actual\n+'\n+\n test_expect_success 'fetching ref and exact OID' '\n \ttest_when_finished \"rm -f log\" &&\n \n-- \n2.47.0\n\n"},{"id":"533035","messageId":"aVu1_FOWqwuVPH9i@pks.im","threadId":"64674","inReplyTo":"20251224003504.52660-2-mats.dodd12@gmail.com","subject":"Re: [PATCH 1/2] upload-pack: send shallow-info before wanted-refs in protocol v2","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-01-05T13:00:44Z","receivedAt":"2026-01-05T13:00:55Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Wed, Dec 24, 2025 at 01:35:03AM +0100, Matthew Dodd wrote:\n> From: Mats-Dodd <mats.dodd12@gmail.com>\n> \n> The protocol v2 specification (Documentation/gitprotocol-v2.adoc) defines\n> the ordering of optional sections in the fetch response as:\n> \n>     [acknowledgments delim-pkt] [shallow-info delim-pkt]\n>     [wanted-refs delim-pkt] [packfile-uris delim-pkt]\n>     packfile flush-pkt\n> \n> However, since the ref-in-want feature was introduced in 516e2b76bdc\n> (upload-pack: implement ref-in-want, 2018-06-27), the server sends\n> wanted-refs before shallow-info. This violates the specification and\n> breaks the client (fetch-pack.c), which expects shallow-info first.\n> \n> When a client performs a shallow clone/fetch against a server with\n> uploadpack.allowRefInWant=true, the client receives sections in the\n> wrong order and fails with:\n> \n>     fatal: expected 'packfile', received 'shallow-info'\n> \n> Fix by swapping the order of send_shallow_info() and\n\nNit: is there a word missing here? E.g. \"Fix this by...\"\n\n> diff --git a/upload-pack.c b/upload-pack.c\n> index 1e87ae9559..029ca93e69 100644\n> --- a/upload-pack.c\n> +++ b/upload-pack.c\n> @@ -1830,8 +1830,8 @@ int upload_pack_v2(struct repository *r, struct packet_reader *request)\n>  \t\t\t\tstate = UPLOAD_DONE;\n>  \t\t\tbreak;\n>  \t\tcase UPLOAD_SEND_PACK:\n> -\t\t\tsend_wanted_ref_info(&data);\n>  \t\t\tsend_shallow_info(&data);\n> +\t\t\tsend_wanted_ref_info(&data);\n\nIndeed. The accompanying code in \"fetch-pack.c\" expects information the\nother way round:\n\n\tif (process_section_header(&reader, \"shallow-info\", 1))\n\t\treceive_shallow_info(args, &reader, shallows, si);\n\n\tif (process_section_header(&reader, \"wanted-refs\", 1))\n\t\treceive_wanted_refs(&reader, sought, nr_sought);\n\nThe bug seems to exist since the inception of this feature. 516e2b76bd\n(upload-pack: implement ref-in-want, 2018-06-27) implements the server\nside in the current-broken way, and 733020517a (fetch-pack: implement\nref-in-want, 2018-06-27) implements the client side in the correct way.\nSo this combination has always been broken, and the fix looks obviously\ncorrect to me indeed.\n\nOne nit though: I don't really think it's necessary to split up this\nseries into two patches. The new test can simply be added to this commit\nhere.\n\nThanks!\n\nPatrick\n"}]}