{"thread":{"id":"65884","subject":"receive-pack hangs on zero-object push into promisor-shaped repository","startedAt":"2026-06-29T07:11:10Z","lastAt":"2026-06-29T15:30:34Z","messageCount":2,"participants":["Wei Hu","Patrick Steinhardt"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"546631","messageId":"CACLXMtCSzW9BY7idqB1yGa87MeG0Y2FN5Ho2hRXuPJ_qswE27Q@mail.gmail.com","threadId":"65884","inReplyTo":null,"subject":"receive-pack hangs on zero-object push into promisor-shaped repository","fromName":"Wei Hu","fromEmail":"weihu.math@gmail.com","sentAt":"2026-06-29T07:10:42Z","receivedAt":"2026-06-29T07:11:10Z","isPatch":false,"body":"Hello,\n\nI found a reproducible hang in `git receive-pack` when pushing a ref update\nthat sends zero objects into a repository that has promisor remote\nconfiguration and `.promisor` pack sidecar files.\n\nThe same zero-object ref update returns normally when the receiving\nrepository\nis a normal non-bare repository or a bare repository. It also returns\nnormally\nif I remove either the promisor remote config or the `.promisor` sidecar\nfiles\nfrom the receiving repository.\n\nCheck the attached script to reproduce the bug.\n\nEnvironment:\n\n  git version 2.54.0\n  cpu: x86_64\n  no commit associated with this build\n  sizeof-long: 8\n  sizeof-size_t: 8\n  shell-path: /bin/sh\n  rust: disabled\n  gettext: enabled\n  libcurl: 8.5.0\n  zlib: 1.3\n  SHA-1: SHA1_DC\n  SHA-256: SHA256_BLK\n  default-ref-format: files\n  default-hash: sha1\n\n  OS: Ubuntu 24.04.4 LTS (Noble Numbat)\n\n\n#!/bin/sh\nset -eu\n\nGIT=${GIT:-git}\nROOT=$(mktemp -d \"${TMPDIR:-/tmp}/git-promisor-push-hang.XXXXXX\")\nSRC=$ROOT/src\nDST=$ROOT/dst\nUPSTREAM=$ROOT/upstream.git\nTRACE=$ROOT/trace.log\n\necho \"root: $ROOT\"\necho \"git: $($GIT --version)\"\n\n$GIT init -q \"$SRC\"\n$GIT -C \"$SRC\" config user.name Repro\n$GIT -C \"$SRC\" config user.email repro@example.invalid\n\nprintf A >\"$SRC/file\"\n$GIT -C \"$SRC\" add file\n$GIT -C \"$SRC\" commit -q -m A\n$GIT -C \"$SRC\" branch topic\nOLD=$($GIT -C \"$SRC\" rev-parse topic)\n\nprintf B >\"$SRC/file\"\n$GIT -C \"$SRC\" commit -q -am B\n$GIT -C \"$SRC\" branch -M main\nNEW=$($GIT -C \"$SRC\" rev-parse main)\n\n$GIT clone -q --bare \"$SRC\" \"$UPSTREAM\"\n$GIT init -q \"$DST\"\n$GIT -C \"$DST\" config receive.denycurrentbranch updateInstead\n$GIT -C \"$SRC\" push -q \"$DST\" main:main topic:topic\n$GIT -C \"$DST\" checkout -q main\n\n$GIT -C \"$DST\" config remote.origin.url \"file://$UPSTREAM\"\n$GIT -C \"$DST\" config remote.origin.promisor true\n$GIT -C \"$DST\" config remote.origin.partialclonefilter blob:none\n$GIT -C \"$DST\" gc -q\nfor pack in \"$DST\"/.git/objects/pack/*.pack\ndo\n\t: >\"${pack%.pack}.promisor\"\ndone\n\n$GIT -C \"$DST\" update-ref refs/heads/topic \"$OLD\"\n\nstatus=0\ntimeout --kill-after=2s 8 \\\n\tenv GIT_TRACE=1 GIT_TRACE_PACKET=1 \\\n\t$GIT -C \"$SRC\" push --porcelain \"$DST\" HEAD:topic \\\n\t>\"$TRACE\" 2>&1 || status=$?\n\nAFTER=$($GIT -C \"$DST\" rev-parse refs/heads/topic)\nZERO_PACK=no\ngrep -q -- '--pack_header=2,0' \"$TRACE\" && ZERO_PACK=yes\n\necho \"old: $OLD\"\necho \"new: $NEW\"\necho \"after: $AFTER\"\necho \"push status: $status\"\necho \"zero-object pack observed: $ZERO_PACK\"\necho \"trace: $TRACE\"\n\nif test \"$status\" = 124 && test \"$AFTER\" = \"$OLD\" && test \"$ZERO_PACK\" = yes\nthen\n\techo \"BUG REPRODUCED\"\n\texit 0\nfi\n\necho \"BUG NOT REPRODUCED\"\nexit 1\n"},{"id":"546675","messageId":"akKPjjfabiRkTbtt@pks.im","threadId":"65884","inReplyTo":"CACLXMtCSzW9BY7idqB1yGa87MeG0Y2FN5Ho2hRXuPJ_qswE27Q@mail.gmail.com","subject":"Re: receive-pack hangs on zero-object push into promisor-shaped repository","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-06-29T15:30:22Z","receivedAt":"2026-06-29T15:30:34Z","isPatch":false,"body":"On Mon, Jun 29, 2026 at 03:10:42PM +0800, Wei Hu wrote:\n> Hello,\n> \n> I found a reproducible hang in `git receive-pack` when pushing a ref update\n> that sends zero objects into a repository that has promisor remote\n> configuration and `.promisor` pack sidecar files.\n> \n> The same zero-object ref update returns normally when the receiving\n> repository is a normal non-bare repository or a bare repository. It\n> also returns normally if I remove either the promisor remote config or\n> the `.promisor` sidecar files from the receiving repository.\n> \n> Check the attached script to reproduce the bug.\n\nThanks for your report! I was able to reduce your test case to the\nfollowing minimal reproducer:\n\ndiff --git a/t/t5616-partial-clone.sh b/t/t5616-partial-clone.sh\nindex 1c2805acca..2850e78e49 100755\n--- a/t/t5616-partial-clone.sh\n+++ b/t/t5616-partial-clone.sh\n@@ -723,6 +723,28 @@ test_expect_success 'after fetching descendants of non-promisor commits, gc work\n \tgit -C partial gc --prune=now\n '\n \n+test_expect_success 'zero-object push does not hang' '\n+\trm -rf src dst &&\n+\n+\tgit init src &&\n+\ttest_commit -C src initial &&\n+\n+\tgit init --bare dst &&\n+\tgit -C src push \"$(pwd)/dst\" main &&\n+\tgit -C dst config set remote.origin.promisor true &&\n+\tgit -C dst maintenance run &&\n+\tfor pack in dst/objects/pack/*.pack\n+\tdo\n+\t\t>\"${pack%.pack}.promisor\" || return 1\n+\tdone &&\n+\n+\t# Push the already-existing commit with a new branch name, which\n+\t# results in zero objects being written. This used to hang in the past.\n+\tgit -C src push \"$(pwd)/dst\" main:topic &&\n+\tgit -C src rev-parse main >expect &&\n+\tgit -C dst rev-parse topic >actual &&\n+\ttest_cmp expect actual\n+'\n \n . \"$TEST_DIRECTORY\"/lib-httpd.sh\n start_httpd\n\nAs it turns out, the bug itself was fixed already via d9982e8290\n(connected: close err_fd in promisor fast-path, 2026-05-15), and that\nfix is going to be part of Git 2.55 (which is due today).\n\nThat commit didn't add a test for this scenario though, even though the\ncommit message points out that there's been multiple regressions in this\narea already. It's probably worth it to add the above test to our test\nsuite. Is this something you'd like to do? Otherwise I'm happy to send a\npatch.\n\nThanks!\n\nPatrick\n"}]}