git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Phillip Wood <phillip.wood123@gmail.com>
To: Karthik Nayak <karthik.188@gmail.com>, git@vger.kernel.org
Cc: ps@pks.im, jltobler@gmail.com, phillip.wood123@gmail.com
Subject: Re: [PATCH v2 6/7] refs: implement partial reference transaction support
Date: Tue, 25 Feb 2025 14:57:47 +0000	[thread overview]
Message-ID: <2755fb78-d587-4ad9-b22f-b60dfa752d7a@gmail.com> (raw)
In-Reply-To: <20250225-245-partially-atomic-ref-updates-v2-6-cfa3236895d7@gmail.com>

Hi Karthik

On 25/02/2025 09:29, Karthik Nayak wrote:
> Git's reference transactions are all-or-nothing: either all updates
> succeed, or none do. While this atomic behavior is generally desirable,
> it can be suboptimal especially when using the reftable backend, where
> batching multiple reference updates into a single transaction is more
> efficient than performing them sequentially.
> 
> Introduce partial transaction support with a new flag,
> 'REF_TRANSACTION_ALLOW_PARTIAL'. When enabled, this flag allows
> individual reference updates that would typically cause the entire
> transaction to fail due to non-system-related errors to be marked as
> rejected while permitting other updates to proceed. Non-system-related
> errors include issues caused by user-provided input values, whereas
> system-related errors, such as I/O failures or memory issues, continue
> to result in a full transaction failure. This approach enhances
> flexibility while preserving transactional integrity where necessary.
> 
> The implementation introduces several key components:
> 
>    - Add 'rejection_err' field to struct `ref_update` to track failed
>      updates with failure reason.
> 
>    - Modify reference backends (files, packed, reftable) to handle
>      partial transactions by using `ref_transaction_set_rejected()`
>      instead of failing the entire transaction when
>      `REF_TRANSACTION_ALLOW_PARTIAL` is set.
> 
>    - Add `ref_transaction_for_each_rejected_update()` to let callers
>      examine which updates were rejected and why.

I think this is a much better design. I wonder if we want to signal to 
the caller of ref_transaction_commit() that there were ignored errors 
rather than forcing them to call ref_transaction_for_each_rejected() to 
find that out. Another possibility would be to call the callback from 
ref_transaction_commit() but that would mean changing the signature of 
ref_transaction_begin() to take the callback and user data when 
REF_TRANSACTION_ALLOW_PARTIAL is passed.

Best Wishes

Phillip

> This foundational change enables partial transaction support throughout
> the reference subsystem. The next commit will expose this capability to
> users by adding a `--allow-partial` flag to 'git-update-ref(1)',
> providing both a user-facing feature and a testable implementation.
> 
> Signed-off-by: Karthik Nayak <karthik.188@gmail.com>
> ---
>   refs.c                  | 31 +++++++++++++++++++++++++++++++
>   refs.h                  | 22 ++++++++++++++++++++++
>   refs/files-backend.c    | 12 +++++++++++-
>   refs/packed-backend.c   | 30 ++++++++++++++++++++++++++++--
>   refs/refs-internal.h    | 13 +++++++++++++
>   refs/reftable-backend.c | 12 +++++++++++-
>   6 files changed, 116 insertions(+), 4 deletions(-)
> 
> diff --git a/refs.c b/refs.c
> index f989a46a5a..243c09c368 100644
> --- a/refs.c
> +++ b/refs.c
> @@ -1211,6 +1211,15 @@ void ref_transaction_free(struct ref_transaction *transaction)
>   	free(transaction);
>   }
>   
> +void ref_transaction_set_rejected(struct ref_transaction *transaction,
> +				  size_t update_idx,
> +				  enum transaction_error err)
> +{
> +	if (update_idx >= transaction->nr)
> +		BUG("trying to set rejection on invalid update index");
> +	transaction->updates[update_idx]->rejection_err = err;
> +}
> +
>   struct ref_update *ref_transaction_add_update(
>   		struct ref_transaction *transaction,
>   		const char *refname, unsigned int flags,
> @@ -1236,6 +1245,7 @@ struct ref_update *ref_transaction_add_update(
>   	transaction->updates[transaction->nr++] = update;
>   
>   	update->flags = flags;
> +	update->rejection_err = TRANSACTION_OK;
>   
>   	update->new_target = xstrdup_or_null(new_target);
>   	update->old_target = xstrdup_or_null(old_target);
> @@ -2726,6 +2736,27 @@ void ref_transaction_for_each_queued_update(struct ref_transaction *transaction,
>   	}
>   }
>   
> +void ref_transaction_for_each_rejected_update(struct ref_transaction *transaction,
> +					      ref_transaction_for_each_rejected_update_fn cb,
> +					      void *cb_data)
> +{
> +	if (!(transaction->flags & REF_TRANSACTION_ALLOW_PARTIAL))
> +		return;
> +
> +	for (size_t i = 0; i < transaction->nr; i++) {
> +		struct ref_update *update = transaction->updates[i];
> +
> +		if (!update->rejection_err)
> +			continue;
> +
> +		cb(update->refname,
> +		   (update->flags & REF_HAVE_OLD) ? &update->old_oid : NULL,
> +		   (update->flags & REF_HAVE_NEW) ? &update->new_oid : NULL,
> +		   update->old_target, update->new_target,
> +		   update->rejection_err, cb_data);
> +	}
> +}
> +
>   int refs_delete_refs(struct ref_store *refs, const char *logmsg,
>   		     struct string_list *refnames, unsigned int flags)
>   {
> diff --git a/refs.h b/refs.h
> index 8e9ead174c..e4a6a8218f 100644
> --- a/refs.h
> +++ b/refs.h
> @@ -675,6 +675,13 @@ enum ref_transaction_flag {
>   	 * either be absent or null_oid.
>   	 */
>   	REF_TRANSACTION_FLAG_INITIAL = (1 << 0),
> +
> +	/*
> +	 * The transaction mechanism by default fails all updates if any conflict
> +	 * is detected. This flag allows transactions to partially apply updates
> +	 * while rejecting updates which do not match the expected state.
> +	 */
> +	REF_TRANSACTION_ALLOW_PARTIAL = (1 << 1),
>   };
>   
>   /*
> @@ -905,6 +912,21 @@ void ref_transaction_for_each_queued_update(struct ref_transaction *transaction,
>   					    ref_transaction_for_each_queued_update_fn cb,
>   					    void *cb_data);
>   
> +/*
> + * Execute the given callback function for each of the reference updates which
> + * have been rejected in the given transaction.
> + */
> +typedef void ref_transaction_for_each_rejected_update_fn(const char *refname,
> +							 const struct object_id *old_oid,
> +							 const struct object_id *new_oid,
> +							 const char *old_target,
> +							 const char *new_target,
> +							 enum transaction_error err,
> +							 void *cb_data);
> +void ref_transaction_for_each_rejected_update(struct ref_transaction *transaction,
> +					      ref_transaction_for_each_rejected_update_fn cb,
> +					      void *cb_data);
> +
>   /*
>    * Free `*transaction` and all associated data.
>    */
> diff --git a/refs/files-backend.c b/refs/files-backend.c
> index 3b0adf8bb2..d0a53c9ace 100644
> --- a/refs/files-backend.c
> +++ b/refs/files-backend.c
> @@ -2851,8 +2851,18 @@ static int files_transaction_prepare(struct ref_store *ref_store,
>   		ret = lock_ref_for_update(refs, update, transaction,
>   					  head_ref, &refnames_to_check,
>   					  err);
> -		if (ret)
> +		if (ret) {
> +			if (transaction->flags & REF_TRANSACTION_ALLOW_PARTIAL &&
> +			    ret != TRANSACTION_GENERIC_ERROR) {
> +				ref_transaction_set_rejected(transaction, i, ret);
> +
> +				strbuf_setlen(err, 0);
> +				ret = TRANSACTION_OK;
> +
> +				continue;
> +			}
>   			goto cleanup;
> +		}
>   
>   		if (update->flags & REF_DELETING &&
>   		    !(update->flags & REF_LOG_ONLY) &&
> diff --git a/refs/packed-backend.c b/refs/packed-backend.c
> index 75e1ebf67d..0857204213 100644
> --- a/refs/packed-backend.c
> +++ b/refs/packed-backend.c
> @@ -1324,10 +1324,11 @@ static int packed_ref_store_remove_on_disk(struct ref_store *ref_store,
>    * remain locked when it is done.
>    */
>   static enum transaction_error write_with_updates(struct packed_ref_store *refs,
> -						 struct string_list *updates,
> +						 struct ref_transaction *transaction,
>   						 struct strbuf *err)
>   {
>   	enum transaction_error ret = TRANSACTION_GENERIC_ERROR;
> +	struct string_list *updates = &transaction->refnames;
>   	struct ref_iterator *iter = NULL;
>   	size_t i;
>   	int ok;
> @@ -1408,6 +1409,14 @@ static enum transaction_error write_with_updates(struct packed_ref_store *refs,
>   						    "reference already exists",
>   						    update->refname);
>   					ret = TRANSACTION_CREATE_EXISTS;
> +
> +					if (transaction->flags & REF_TRANSACTION_ALLOW_PARTIAL) {
> +						ref_transaction_set_rejected(transaction, i, ret);
> +						strbuf_setlen(err, 0);
> +						ret = 0;
> +						continue;
> +					}
> +
>   					goto error;
>   				} else if (!oideq(&update->old_oid, iter->oid)) {
>   					strbuf_addf(err, "cannot update ref '%s': "
> @@ -1416,6 +1425,14 @@ static enum transaction_error write_with_updates(struct packed_ref_store *refs,
>   						    oid_to_hex(iter->oid),
>   						    oid_to_hex(&update->old_oid));
>   					ret = TRANSACTION_INCORRECT_OLD_VALUE;
> +
> +					if (transaction->flags & REF_TRANSACTION_ALLOW_PARTIAL) {
> +						ref_transaction_set_rejected(transaction, i, ret);
> +						strbuf_setlen(err, 0);
> +						ret = 0;
> +						continue;
> +					}
> +
>   					goto error;
>   				}
>   			}
> @@ -1453,6 +1470,14 @@ static enum transaction_error write_with_updates(struct packed_ref_store *refs,
>   					    update->refname,
>   					    oid_to_hex(&update->old_oid));
>   				return TRANSACTION_NONEXISTENT_REF;
> +
> +				if (transaction->flags & REF_TRANSACTION_ALLOW_PARTIAL) {
> +					ref_transaction_set_rejected(transaction, i, ret);
> +					strbuf_setlen(err, 0);
> +					ret = 0;
> +					continue;
> +				}
> +
>   				goto error;
>   			}
>   		}
> @@ -1518,6 +1543,7 @@ static enum transaction_error write_with_updates(struct packed_ref_store *refs,
>   write_error:
>   	strbuf_addf(err, "error writing to %s: %s",
>   		    get_tempfile_path(refs->tempfile), strerror(errno));
> +	ret = TRANSACTION_GENERIC_ERROR;
>   
>   error:
>   	ref_iterator_free(iter);
> @@ -1676,7 +1702,7 @@ static int packed_transaction_prepare(struct ref_store *ref_store,
>   		data->own_lock = 1;
>   	}
>   
> -	ret = write_with_updates(refs, &transaction->refnames, err);
> +	ret = write_with_updates(refs, transaction, err);
>   	if (ret)
>   		goto failure;
>   
> diff --git a/refs/refs-internal.h b/refs/refs-internal.h
> index c97045fbed..7196f2d880 100644
> --- a/refs/refs-internal.h
> +++ b/refs/refs-internal.h
> @@ -123,6 +123,11 @@ struct ref_update {
>   	 */
>   	uint64_t index;
>   
> +	/*
> +	 * Used in partial transactions to mark if a given update was rejected.
> +	 */
> +	enum transaction_error rejection_err;
> +
>   	/*
>   	 * If this ref_update was split off of a symref update via
>   	 * split_symref_update(), then this member points at that
> @@ -142,6 +147,14 @@ int refs_read_raw_ref(struct ref_store *ref_store, const char *refname,
>   		      struct object_id *oid, struct strbuf *referent,
>   		      unsigned int *type, int *failure_errno);
>   
> +/*
> + * Mark a given update as rejected with a given reason. To be used in conjuction
> + * with the `REF_TRANSACTION_ALLOW_PARTIAL` flag to allow partial transactions.
> + */
> +void ref_transaction_set_rejected(struct ref_transaction *transaction,
> +				  size_t update_idx,
> +				  enum transaction_error err);
> +
>   /*
>    * Add a ref_update with the specified properties to transaction, and
>    * return a pointer to the new object. This function does not verify
> diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c
> index e1fd9c2de2..83cf8d582b 100644
> --- a/refs/reftable-backend.c
> +++ b/refs/reftable-backend.c
> @@ -1374,8 +1374,18 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store,
>   					    transaction->updates[i],
>   					    &refnames_to_check, head_type,
>   					    &head_referent, &referent, err);
> -		if (ret)
> +		if (ret) {
> +			if (transaction->flags & REF_TRANSACTION_ALLOW_PARTIAL &&
> +			    ret != TRANSACTION_GENERIC_ERROR) {
> +				ref_transaction_set_rejected(transaction, i, ret);
> +
> +				strbuf_setlen(err, 0);
> +				ret = TRANSACTION_OK;
> +
> +				continue;
> +			}
>   			goto done;
> +		}
>   	}
>   
>   	string_list_sort(&refnames_to_check);
> 


  parent reply	other threads:[~2025-02-25 14:57 UTC|newest]

Thread overview: 147+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-02-07  7:34 [PATCH 0/6] refs: introduce support for partial reference transactions Karthik Nayak
2025-02-07  7:34 ` [PATCH 1/6] refs/files: remove duplicate check in `split_symref_update()` Karthik Nayak
2025-02-07 16:12   ` Patrick Steinhardt
2025-02-11  6:35     ` Karthik Nayak
2025-02-07  7:34 ` [PATCH 2/6] refs: move duplicate refname update check to generic layer Karthik Nayak
2025-02-07 16:12   ` Patrick Steinhardt
2025-02-11 10:33     ` Karthik Nayak
2025-02-07  7:34 ` [PATCH 3/6] refs/files: remove duplicate duplicates check Karthik Nayak
2025-02-07 16:12   ` Patrick Steinhardt
2025-02-07  7:34 ` [PATCH 4/6] refs/reftable: extract code from the transaction preparation Karthik Nayak
2025-02-07  7:34 ` [PATCH 5/6] refs: implement partial reference transaction support Karthik Nayak
2025-02-07 16:12   ` Patrick Steinhardt
2025-02-21 10:33     ` Karthik Nayak
2025-02-07  7:34 ` [PATCH 6/6] update-ref: add --allow-partial flag for stdin mode Karthik Nayak
2025-02-07 16:12   ` Patrick Steinhardt
2025-02-21 11:45     ` Karthik Nayak
2025-02-11 17:03 ` [PATCH 0/6] refs: introduce support for partial reference transactions Phillip Wood
2025-02-11 17:40   ` Phillip Wood
2025-02-12 12:36     ` Karthik Nayak
2025-02-12 12:34   ` Karthik Nayak
2025-02-19 14:34     ` Phillip Wood
2025-02-19 15:10       ` Patrick Steinhardt
2025-02-21 11:50       ` Karthik Nayak
2025-02-25  9:29 ` [PATCH v2 0/7] " Karthik Nayak
2025-02-25  9:29   ` [PATCH v2 1/7] refs/files: remove redundant check in split_symref_update() Karthik Nayak
2025-02-25  9:29   ` [PATCH v2 2/7] refs: move duplicate refname update check to generic layer Karthik Nayak
2025-02-25  9:29   ` [PATCH v2 3/7] refs/files: remove duplicate duplicates check Karthik Nayak
2025-02-25  9:29   ` [PATCH v2 4/7] refs/reftable: extract code from the transaction preparation Karthik Nayak
2025-02-25  9:29   ` [PATCH v2 5/7] refs: introduce enum-based transaction error types Karthik Nayak
2025-02-25 11:08     ` Patrick Steinhardt
2025-03-03 20:12       ` Karthik Nayak
2025-02-25  9:29   ` [PATCH v2 6/7] refs: implement partial reference transaction support Karthik Nayak
2025-02-25 11:07     ` Patrick Steinhardt
2025-03-03 20:17       ` Karthik Nayak
2025-02-25 14:57     ` Phillip Wood [this message]
2025-03-03 20:21       ` Karthik Nayak
2025-03-04 10:31         ` Phillip Wood
2025-03-05 14:20           ` Karthik Nayak
2025-02-25  9:29   ` [PATCH v2 7/7] update-ref: add --allow-partial flag for stdin mode Karthik Nayak
2025-02-25 11:08     ` Patrick Steinhardt
2025-03-03 20:22       ` Karthik Nayak
2025-02-25 14:59     ` Phillip Wood
2025-03-03 20:34       ` Karthik Nayak
2025-03-05 17:38 ` [PATCH v3 0/8] refs: introduce support for partial reference transactions Karthik Nayak
2025-03-05 17:38   ` [PATCH v3 1/8] refs/files: remove redundant check in split_symref_update() Karthik Nayak
2025-03-05 21:20     ` Junio C Hamano
2025-03-06  9:13       ` Karthik Nayak
2025-03-05 17:38   ` [PATCH v3 2/8] refs: move duplicate refname update check to generic layer Karthik Nayak
2025-03-05 21:56     ` Junio C Hamano
2025-03-06  9:46       ` Karthik Nayak
2025-03-05 17:38   ` [PATCH v3 3/8] refs/files: remove duplicate duplicates check Karthik Nayak
2025-03-05 17:38   ` [PATCH v3 4/8] refs/reftable: extract code from the transaction preparation Karthik Nayak
2025-03-05 17:39   ` [PATCH v3 5/8] refs: introduce enum-based transaction error types Karthik Nayak
2025-03-05 17:39   ` [PATCH v3 6/8] refs: implement partial reference transaction support Karthik Nayak
2025-03-07 19:50     ` Jeff King
2025-03-07 20:46       ` Junio C Hamano
2025-03-07 20:48         ` Junio C Hamano
2025-03-07 21:05         ` Karthik Nayak
2025-03-07 22:54         ` [PATCH] config.mak.dev: enable -Wunreachable-code Jeff King
2025-03-07 23:28           ` Junio C Hamano
2025-03-08  3:23           ` Jeff King
2025-03-10 15:40             ` Junio C Hamano
2025-03-10 16:04               ` Jeff King
2025-03-10 18:50                 ` Junio C Hamano
2025-03-14 16:10                   ` Jeff King
2025-03-14 16:13                     ` Jeff King
2025-03-14 17:27                       ` Junio C Hamano
2025-03-14 17:40                         ` Junio C Hamano
2025-03-14 17:43                           ` Patrick Steinhardt
2025-03-14 18:53                           ` Jeff King
2025-03-14 19:50                             ` Junio C Hamano
2025-03-14 17:15                     ` Junio C Hamano
2025-06-03 21:29             ` Mike Hommey
2025-06-03 22:07               ` Junio C Hamano
2025-06-03 22:37                 ` Mike Hommey
2025-06-03 23:08                   ` Mike Hommey
2025-03-14 21:09           ` [PATCH v2 0/3] -Wunreachable-code Junio C Hamano
2025-03-14 21:09             ` [PATCH v2 1/3] config.mak.dev: enable -Wunreachable-code Junio C Hamano
2025-03-14 21:09             ` [PATCH v2 2/3] run-command: use errno to check for sigfillset() error Junio C Hamano
2025-03-17 21:30               ` Taylor Blau
2025-03-17 23:12                 ` Junio C Hamano
2025-03-18  0:36                   ` Junio C Hamano
2025-03-14 21:09             ` [PATCH v2 3/3] git-compat-util: add NOT_A_CONST macro and use it in atfork_prepare() Junio C Hamano
2025-03-14 22:29               ` Junio C Hamano
2025-03-17 18:00                 ` Jeff King
2025-03-17 23:53             ` [PATCH v3 0/3] -Wunreachable-code Junio C Hamano
2025-03-17 23:53               ` [PATCH v3 1/3] run-command: use errno to check for sigfillset() error Junio C Hamano
2025-03-17 23:53               ` [PATCH v3 2/3] git-compat-util: add NOT_CONSTANT macro and use it in atfork_prepare() Junio C Hamano
2025-03-18  0:20                 ` Jeff King
2025-03-18  0:28                   ` Junio C Hamano
2025-03-18 22:04                 ` Calvin Wan
2025-03-18 22:26                   ` Calvin Wan
2025-03-18 23:55                     ` Junio C Hamano
2025-03-17 23:53               ` [PATCH v3 3/3] config.mak.dev: enable -Wunreachable-code Junio C Hamano
2025-03-18  0:18               ` [PATCH v3 0/3] -Wunreachable-code Jeff King
2025-03-07 21:02       ` [PATCH v3 6/8] refs: implement partial reference transaction support Karthik Nayak
2025-03-07 19:57     ` Jeff King
2025-03-07 21:07       ` Karthik Nayak
2025-03-05 17:39   ` [PATCH v3 7/8] refs: support partial update rejections during F/D checks Karthik Nayak
2025-03-05 17:39   ` [PATCH v3 8/8] update-ref: add --allow-partial flag for stdin mode Karthik Nayak
2025-03-05 19:28   ` [PATCH v3 0/8] refs: introduce support for partial reference transactions Junio C Hamano
2025-03-06  9:06     ` Karthik Nayak
2025-03-20 11:43 ` [PATCH v4 0/8] refs: introduce support for batched reference updates Karthik Nayak
2025-03-20 11:43   ` [PATCH v4 1/8] refs/files: remove redundant check in split_symref_update() Karthik Nayak
2025-03-20 11:43   ` [PATCH v4 2/8] refs: move duplicate refname update check to generic layer Karthik Nayak
2025-03-20 11:43   ` [PATCH v4 3/8] refs/files: remove duplicate duplicates check Karthik Nayak
2025-03-20 11:43   ` [PATCH v4 4/8] refs/reftable: extract code from the transaction preparation Karthik Nayak
2025-03-20 11:44   ` [PATCH v4 5/8] refs: introduce enum-based transaction error types Karthik Nayak
2025-03-20 20:26     ` Patrick Steinhardt
2025-03-24 14:50       ` Karthik Nayak
2025-03-25 12:31         ` Patrick Steinhardt
2025-03-20 11:44   ` [PATCH v4 6/8] refs: implement batch reference update support Karthik Nayak
2025-03-20 20:26     ` Patrick Steinhardt
2025-03-24 14:54       ` Karthik Nayak
2025-03-20 11:44   ` [PATCH v4 7/8] refs: support rejection in batch updates during F/D checks Karthik Nayak
2025-03-24 13:08     ` Patrick Steinhardt
2025-03-24 17:48       ` Karthik Nayak
2025-03-25 12:31         ` Patrick Steinhardt
2025-03-20 11:44   ` [PATCH v4 8/8] update-ref: add --batch-updates flag for stdin mode Karthik Nayak
2025-03-24 13:08     ` Patrick Steinhardt
2025-03-24 17:51       ` Karthik Nayak
2025-03-27 11:13 ` [PATCH v5 0/8] refs: introduce support for batched reference updates Karthik Nayak
2025-03-27 11:13   ` [PATCH v5 1/8] refs/files: remove redundant check in split_symref_update() Karthik Nayak
2025-03-27 11:13   ` [PATCH v5 2/8] refs: move duplicate refname update check to generic layer Karthik Nayak
2025-03-27 11:13   ` [PATCH v5 3/8] refs/files: remove duplicate duplicates check Karthik Nayak
2025-03-27 11:13   ` [PATCH v5 4/8] refs/reftable: extract code from the transaction preparation Karthik Nayak
2025-03-27 11:13   ` [PATCH v5 5/8] refs: introduce enum-based transaction error types Karthik Nayak
2025-03-27 11:13   ` [PATCH v5 6/8] refs: implement batch reference update support Karthik Nayak
2025-03-27 11:13   ` [PATCH v5 7/8] refs: support rejection in batch updates during F/D checks Karthik Nayak
2025-03-27 11:13   ` [PATCH v5 8/8] update-ref: add --batch-updates flag for stdin mode Karthik Nayak
2025-03-28 13:00     ` Jean-Noël AVILA
2025-03-29 16:36       ` Junio C Hamano
2025-03-29 18:18         ` Karthik Nayak
2025-03-28  9:24   ` [PATCH v5 0/8] refs: introduce support for batched reference updates Patrick Steinhardt
2025-04-08  8:51 ` [PATCH v6 " Karthik Nayak
2025-04-08  8:51   ` [PATCH v6 1/8] refs/files: remove redundant check in split_symref_update() Karthik Nayak
2025-04-08  8:51   ` [PATCH v6 2/8] refs: move duplicate refname update check to generic layer Karthik Nayak
2025-04-08  8:51   ` [PATCH v6 3/8] refs/files: remove duplicate duplicates check Karthik Nayak
2025-04-08  8:51   ` [PATCH v6 4/8] refs/reftable: extract code from the transaction preparation Karthik Nayak
2025-04-08  8:51   ` [PATCH v6 5/8] refs: introduce enum-based transaction error types Karthik Nayak
2025-04-08  8:51   ` [PATCH v6 6/8] refs: implement batch reference update support Karthik Nayak
2025-04-08  8:51   ` [PATCH v6 7/8] refs: support rejection in batch updates during F/D checks Karthik Nayak
2025-04-08  8:51   ` [PATCH v6 8/8] update-ref: add --batch-updates flag for stdin mode Karthik Nayak
2025-04-08 15:02     ` Junio C Hamano
2025-04-08 15:26       ` Karthik Nayak
2025-04-08 17:37         ` Junio C Hamano
2025-04-10 11:23           ` 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=2755fb78-d587-4ad9-b22f-b60dfa752d7a@gmail.com \
    --to=phillip.wood123@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=jltobler@gmail.com \
    --cc=karthik.188@gmail.com \
    --cc=phillip.wood@dunelm.org.uk \
    --cc=ps@pks.im \
    /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).