Git development
 help / color / mirror / Atom feed
From: Taylor Blau <ttaylorr@openai.com>
To: git@vger.kernel.org, git@vger.kernel.org
Cc: Jeff King <peff@peff.net>, Junio C Hamano <gitster@pobox.com>
Subject: [PATCH 4/4] send-pack: honor `no-ref-delta` capability
Date: Sun, 12 Jul 2026 18:12:07 -0700	[thread overview]
Message-ID: <alQ7Z8V9gJq2Pq33@com-79390> (raw)
In-Reply-To: <cover.1783905084.git.ttaylorr@openai.com>

Add a 'no-ref-delta' receive-pack capability and teach send-pack to pass
'--no-ref-delta' to 'pack-objects' when the server advertises it.

Keep this separate from 'ofs-delta' so that a server may request that
`send-pack` omit `REF_DELTA` without also accepting `OFS_DELTA`.

Signed-off-by: Taylor Blau <ttaylorr@openai.com>
---
 Documentation/gitprotocol-capabilities.adoc | 17 ++++++++++++++---
 builtin/receive-pack.c                      |  5 +++++
 send-pack.c                                 |  4 ++++
 send-pack.h                                 |  1 +
 t/t5516-fetch-push.sh                       | 14 ++++++++++++++
 5 files changed, 38 insertions(+), 3 deletions(-)

diff --git a/Documentation/gitprotocol-capabilities.adoc b/Documentation/gitprotocol-capabilities.adoc
index 2cf7735be4..bbe88defdf 100644
--- a/Documentation/gitprotocol-capabilities.adoc
+++ b/Documentation/gitprotocol-capabilities.adoc
@@ -34,9 +34,9 @@ were sent.  Server MUST NOT ignore capabilities that client requested
 and server advertised.  As a consequence of these rules, server MUST
 NOT advertise capabilities it does not understand.
 
-The 'atomic', 'report-status', 'report-status-v2', 'delete-refs', 'quiet',
-and 'push-cert' capabilities are sent and recognized by the receive-pack
-(push to server) process.
+The 'atomic', 'report-status', 'report-status-v2', 'delete-refs',
+'no-ref-delta', 'quiet', and 'push-cert' capabilities are sent and
+recognized by the receive-pack (push to server) process.
 
 The 'ofs-delta' and 'side-band-64k' capabilities are sent and recognized
 by both upload-pack and receive-pack protocols.  The 'agent' and 'session-id'
@@ -174,6 +174,17 @@ The server can send, and the client can understand, PACKv2 with delta referring
 its base by position in pack rather than by an obj-id.  That is, they can
 send/read OBJ_OFS_DELTA (aka type 6) in a packfile.
 
+no-ref-delta
+------------
+
+The receive-pack server can request, and the client can send, PACKv2
+without deltas referring to their bases by an obj-id. That is, the
+client MUST NOT send OBJ_REF_DELTA (aka type 7) in a packfile when the
+server advertises this capability.
+
+This does not imply that the server understands OBJ_OFS_DELTA entries;
+that is negotiated separately with the 'ofs-delta' capability.
+
 agent
 -----
 
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index 19eb6a1b61..1c516cbdc6 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -66,6 +66,7 @@ static struct strbuf fsck_msg_types = STRBUF_INIT;
 static int receive_unpack_limit = -1;
 static int transfer_unpack_limit = -1;
 static int advertise_atomic_push = 1;
+static int advertise_no_ref_delta;
 static int advertise_push_options;
 static int advertise_sid;
 static int unpack_limit = 100;
@@ -290,6 +291,8 @@ static void show_ref(const char *path, const struct object_id *oid)
 			strbuf_addstr(&cap, " atomic");
 		if (prefer_ofs_delta)
 			strbuf_addstr(&cap, " ofs-delta");
+		if (advertise_no_ref_delta)
+			strbuf_addstr(&cap, " no-ref-delta");
 		if (push_cert_nonce)
 			strbuf_addf(&cap, " push-cert=%s", push_cert_nonce);
 		if (advertise_push_options)
@@ -2631,6 +2634,8 @@ int cmd_receive_pack(int argc,
 		OPT_HIDDEN_BOOL(0, "http-backend-info-refs", &advertise_refs, NULL),
 		OPT_ALIAS(0, "advertise-refs", "http-backend-info-refs"),
 		OPT_HIDDEN_BOOL(0, "reject-thin-pack-for-testing", &reject_thin, NULL),
+		OPT_HIDDEN_BOOL(0, "advertise-no-ref-delta-for-testing",
+				&advertise_no_ref_delta, NULL),
 		OPT_END()
 	};
 
diff --git a/send-pack.c b/send-pack.c
index 3bb5afc687..2beb1c4be9 100644
--- a/send-pack.c
+++ b/send-pack.c
@@ -80,6 +80,8 @@ static int pack_objects(struct repository *r,
 		strvec_push(&po.args, "--thin");
 	if (args->use_ofs_delta)
 		strvec_push(&po.args, "--delta-base-offset");
+	if (args->no_ref_delta)
+		strvec_push(&po.args, "--no-ref-delta");
 	if (args->quiet || !args->progress)
 		strvec_push(&po.args, "-q");
 	if (args->progress)
@@ -570,6 +572,8 @@ int send_pack(struct repository *r,
 		allow_deleting_refs = 1;
 	if (server_supports("ofs-delta"))
 		args->use_ofs_delta = 1;
+	if (server_supports("no-ref-delta"))
+		args->no_ref_delta = 1;
 	if (server_supports("side-band-64k"))
 		use_sideband = 1;
 	if (server_supports("quiet"))
diff --git a/send-pack.h b/send-pack.h
index 13850c98bb..30be2be0f2 100644
--- a/send-pack.h
+++ b/send-pack.h
@@ -28,6 +28,7 @@ struct send_pack_args {
 		force_update:1,
 		use_thin_pack:1,
 		use_ofs_delta:1,
+		no_ref_delta:1,
 		dry_run:1,
 		/* One of the SEND_PACK_PUSH_CERT_* constants. */
 		push_cert:2,
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index 1b986349a8..c00074afe8 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -1548,6 +1548,20 @@ EOF
 	git push --no-thin --receive-pack="$rcvpck" no-thin/.git refs/heads/main:refs/heads/foo
 '
 
+test_expect_success 'push honors no-ref-delta capability' '
+	test_commit no-ref-delta &&
+
+	rcvpck="git receive-pack --advertise-no-ref-delta-for-testing" &&
+
+	GIT_TRACE2_EVENT="$PWD/no-ref-delta" \
+	git push --receive-pack="$rcvpck" no-thin/.git \
+		refs/heads/main:refs/heads/bar &&
+
+	test_subcommand git pack-objects --all-progress-implied --revs \
+		--stdout --thin --delta-base-offset --no-ref-delta -q \
+		<no-ref-delta
+'
+
 test_expect_success 'pushing a tag pushes the tagged object' '
 	blob=$(echo unreferenced | git hash-object -w --stdin) &&
 	git tag -m foo tag-of-blob $blob &&
-- 
2.55.0

      parent reply	other threads:[~2026-07-13  1:12 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <cover.1783905084.git.ttaylorr@openai.com>
2026-07-13  1:11 ` [PATCH 1/4] t/helper: teach pack-deltas to list delta entries Taylor Blau
2026-07-13  1:11 ` [PATCH 2/4] pack-objects: introduce `--no-ref-delta` Taylor Blau
2026-07-13  1:12 ` [PATCH 3/4] pack-objects: support reuse with `--no-ref-delta` Taylor Blau
2026-07-13  1:12 ` Taylor Blau [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=alQ7Z8V9gJq2Pq33@com-79390 \
    --to=ttaylorr@openai.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=peff@peff.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox