From: Patrick Steinhardt <ps@pks.im>
To: Karthik Nayak <karthik.188@gmail.com>
Cc: git@vger.kernel.org, jltobler@gmail.com, gitster@pobox.com,
sunshine@sunshineco.com,
Christian Couder <chriscool@tuxfamily.org>
Subject: Re: [PATCH v2 2/2] receive-pack: handle reference deletions separately
Date: Thu, 5 Jun 2025 10:47:26 +0200 [thread overview]
Message-ID: <aEFZnmjoxjopv2xF@pks.im> (raw)
In-Reply-To: <20250605-6769-address-test-failures-in-the-next-branch-caused-by-batched-reference-updates-v2-2-26cd05b8a79e@gmail.com>
On Thu, Jun 05, 2025 at 10:19:55AM +0200, Karthik Nayak wrote:
> In 9d2962a7c4 (receive-pack: use batched reference updates, 2025-05-19)
> we updated the 'git-receive-pack(1)' command to use batched reference
> updates. One edge case which was missed during this implementation was
> when a user pushes multiple branches such as:
>
> delete refs/heads/branch/conflict
> create refs/heads/branch
>
> Before using batched updates, the references would be applied
> sequentially and hence no conflicts would arise. With batched updates,
> while the first update applies, the second fails due to F/D conflict. A
> similar issue was present in 'git-fetch(1)' and was fixed by using
> separating out reference pruning into a separate transaction. Apply a
> similar mechanism for 'git-receive-pack(1)' and separate out reference
> deletions into its own batch.
>
> This means 'git-receive-pack(1)' will now use exactly two transactions,
> whereas before using batched updates it would use _at least_ two
> transactions. So using batched updates is the still the better option.
s/the still the/still the/
> diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
> index 9e3cfb85cf..34db4377ca 100644
> --- a/builtin/receive-pack.c
> +++ b/builtin/receive-pack.c
> @@ -1867,47 +1867,66 @@ static void execute_commands_non_atomic(struct command *commands,
> const char *reported_error = NULL;
> struct strmap failed_refs = STRMAP_INIT;
>
> - transaction = ref_store_transaction_begin(get_main_ref_store(the_repository),
> - REF_TRANSACTION_ALLOW_FAILURE, &err);
> - if (!transaction) {
> - rp_error("%s", err.buf);
> - strbuf_reset(&err);
> - reported_error = "transaction failed to start";
> - goto failure;
> - }
> + /*
> + * Reference updates, where F/D conflicts shouldn't arise due to
> + * one reference being deleted, while the other being created
> + * are treated as conflicts in batched updates. This is because
> + * we don't do conflict resolution inside a transaction. To
> + * mitigate this, delete references in a separate batch.
> + */
> + enum processing_phase {
> + PHASE_DELETIONS,
> + PHASE_OTHERS
> + };
>
> - for (cmd = commands; cmd; cmd = cmd->next) {
> - if (!should_process_cmd(cmd) || cmd->run_proc_receive)
> - continue;
> + for (int phase = PHASE_DELETIONS; phase <= PHASE_OTHERS; phase++) {
s/int/enum processing_phase/
Doesn't make any difference, but it feels a bit cleaner.
> + transaction = ref_store_transaction_begin(get_main_ref_store(the_repository),
> + REF_TRANSACTION_ALLOW_FAILURE, &err);
> + if (!transaction) {
> + rp_error("%s", err.buf);
> + strbuf_reset(&err);
> + reported_error = "transaction failed to s1tart";
> + goto failure;
> + }
So if the transaction doesn't contain any deletions we'd now commit an
empty transaction. The same is true the other way round, in case there
are only deletions. Do we maybe want to skip phases when there is no
match? Ideally, we wouldn't even be starting a transaction.
We could for example skip forward to the first command that we would
have to queue. If there is no such command we continue the loop, if
there is we can remember that command, begin the transaction and start
queueing from there.
> @@ -2024,6 +2043,9 @@ static void execute_commands(struct command *commands,
> /*
> * If there is no command ready to run, should return directly to destroy
> * temporary data in the quarantine area.
> + *
> + * Check if any reference deletions exist, these are batched together in
> + * a separate transaction to avoid F/D conflicts with other updates.
> */
Is this comment still accurate?
> for (cmd = commands; cmd && cmd->error_string; cmd = cmd->next)
> ; /* nothing */
> diff --git a/t/t1416-ref-transaction-hooks.sh b/t/t1416-ref-transaction-hooks.sh
> index d91dd3a3b5..b2aaa1908f 100755
> --- a/t/t1416-ref-transaction-hooks.sh
> +++ b/t/t1416-ref-transaction-hooks.sh
> @@ -119,6 +119,8 @@ test_expect_success 'interleaving hook calls succeed' '
> EOF
>
> cat >expect <<-EOF &&
> + hooks/reference-transaction prepared
> + hooks/reference-transaction committed
Yeah, this shows the empty commits indeed.
Patrick
next prev parent reply other threads:[~2025-06-05 8:47 UTC|newest]
Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-06-02 9:57 [PATCH 0/3] refs: fix some bugs with batched-updates Karthik Nayak
2025-06-02 9:57 ` [PATCH 1/3] refs/files: skip updates with errors in batched updates Karthik Nayak
2025-06-02 12:00 ` Patrick Steinhardt
2025-06-02 12:46 ` Karthik Nayak
2025-06-02 15:06 ` Junio C Hamano
2025-06-02 17:13 ` Karthik Nayak
2025-06-02 9:57 ` [PATCH 2/3] t5516: use double quotes for tests with variables Karthik Nayak
2025-06-02 16:59 ` Eric Sunshine
2025-06-02 17:13 ` Karthik Nayak
2025-06-02 9:57 ` [PATCH 3/3] receive-pack: handle reference deletions separately Karthik Nayak
2025-06-02 11:59 ` Patrick Steinhardt
2025-06-02 12:54 ` Karthik Nayak
2025-06-02 15:20 ` Junio C Hamano
2025-06-02 15:56 ` Patrick Steinhardt
2025-06-04 11:08 ` Karthik Nayak
2025-06-05 8:19 ` [PATCH v2 0/2] refs: fix some bugs with batched-updates Karthik Nayak
2025-06-05 8:19 ` [PATCH v2 1/2] refs/files: skip updates with errors in batched updates Karthik Nayak
2025-06-05 8:19 ` [PATCH v2 2/2] receive-pack: handle reference deletions separately Karthik Nayak
2025-06-05 8:47 ` Patrick Steinhardt [this message]
2025-06-05 9:08 ` Karthik Nayak
2025-06-06 8:41 ` [PATCH v3 0/2] refs: fix some bugs with batched-updates Karthik Nayak
2025-06-06 8:41 ` [PATCH v3 1/2] refs/files: skip updates with errors in batched updates Karthik Nayak
2025-06-06 8:41 ` [PATCH v3 2/2] receive-pack: handle reference deletions separately Karthik Nayak
2025-06-12 17:03 ` Christian Couder
2025-06-12 20:40 ` Junio C Hamano
2025-06-13 7:23 ` Karthik Nayak
2025-06-13 8:10 ` [PATCH v4 0/2] refs: fix some bugs with batched-updates Karthik Nayak
2025-06-13 8:10 ` [PATCH v4 1/2] refs/files: skip updates with errors in batched updates Karthik Nayak
2025-06-13 8:10 ` [PATCH v4 2/2] receive-pack: handle reference deletions separately Karthik Nayak
2025-06-13 15:46 ` Junio C Hamano
2025-06-19 9:39 ` Karthik Nayak
2025-06-13 12:43 ` [PATCH v4 0/2] refs: fix some bugs with batched-updates Christian Couder
2025-06-13 18:57 ` Junio C Hamano
2025-06-20 7:15 ` [PATCH v5 " Karthik Nayak
2025-06-20 7:15 ` [PATCH v5 1/2] refs/files: skip updates with errors in batched updates Karthik Nayak
2025-06-20 7:15 ` [PATCH v5 2/2] receive-pack: handle reference deletions separately Karthik Nayak
2025-06-20 16:21 ` [PATCH v5 0/2] refs: fix some bugs with batched-updates Junio C Hamano
2025-06-21 11:08 ` Karthik Nayak
2025-06-22 4:23 ` Junio C Hamano
2025-06-22 14:20 ` Karthik Nayak
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=aEFZnmjoxjopv2xF@pks.im \
--to=ps@pks.im \
--cc=chriscool@tuxfamily.org \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=jltobler@gmail.com \
--cc=karthik.188@gmail.com \
--cc=sunshine@sunshineco.com \
/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;
as well as URLs for NNTP newsgroup(s).