git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v6 0/7] refs: add support for transactional symref updates

From
Karthik Nayak <karthik.188@gmail.com>
Date
May 3, 2024, 12:41 UTC
Message-ID
<20240503124115.252413-1-knayak@gitlab.com>
In-Reply-To
<20240501202229.2695774-1-knayak@gitlab.com>
From: Karthik Nayak <karthik.188@gmail.com>

The patch series takes over from the existing patch series, wherein we introduced symref-* commands to git-update-ref. Since there was a ton of discussions on the UX of the patch series and its application, I thought it would be best to shorten the series and split it into multiple smaller series.

This series adds transactional support for symrefs in the reference db. Then we switch refs_create_symref() to start using transactions for symref updates. This allows us to deprecate the create_symref code in the ref_storage_be interface and remove all associated code which is no longer used.

The split was primarily done so we can merge the non-user facing parts of the previous series. While pertaining the user facing components into another set of patches wherein deeper discussion on the UX can be held without worrying about the internal implementation. Also by using this new functionality in a pre-existing command, we can leverage the existing tests to catch any inconsistencies. One of which was how 'git-symbolic-ref' doesn't add reflog for dangling symrefs, which I've modified my patch to do the same.

We also modify the reference transaction hook to support symrefs. For any symref update the reference transaction hook will output the value with a 'ref:' prefix.

Previous versions:
V1: https://lore.kernel.org/git/20240330224623.579457-1-knayak@gitlab.com/
V2: https://lore.kernel.org/git/20240412095908.1134387-1-knayak@gitlab.com/
V3: https://lore.kernel.org/git/20240423212818.574123-1-knayak@gitlab.com/
V4: https://lore.kernel.org/r/20240426152449.228860-1-knayak@gitlab.com
V5: https://lore.kernel.org/r/20240501202229.2695774-1-knayak@gitlab.com
Changes over v5 are:
- More user friendly error messages.
- `create_symref_lock` now writes to an err buf, instead of directly to stderr.
- Refactor code to make it easier to read around logical operations.
- Cleanup commit message and fix typos.
Thanks to all reviewers!
Range diff:
1:  a354190905 = 1:  a354190905 refs: accept symref values in `ref_transaction_update()`
2:  7dff21dbef ! 2:  0d9c5b9804 files-backend: extract out `create_symref_lock()`
    @@ refs/files-backend.c: static void update_symref_reflog(struct files_ref_store *r
     -				const char *target, const char *logmsg)
     +static int create_symref_lock(struct files_ref_store *refs,
     +			      struct ref_lock *lock, const char *refname,
    -+			      const char *target)
    ++			      const char *target, struct strbuf *err)
      {
    -+	if (!fdopen_lock_file(&lock->lk, "w"))
    -+		return error("unable to fdopen %s: %s",
    ++	if (!fdopen_lock_file(&lock->lk, "w")) {
    ++		strbuf_addf(err, "unable to fdopen %s: %s",
     +			     get_lock_file_path(&lock->lk), strerror(errno));
    ++		return -1;
    ++	}
     +
    -+	if (fprintf(get_lock_file_fp(&lock->lk), "ref: %s\n", target) < 0)
    -+		return error("unable to fprintf %s: %s",
    ++	if (fprintf(get_lock_file_fp(&lock->lk), "ref: %s\n", target) < 0) {
    ++		strbuf_addf(err, "unable to write to %s: %s",
     +			     get_lock_file_path(&lock->lk), strerror(errno));
    ++		return -1;
    ++	}
    ++
     +	return 0;
     +}
     +
    @@ refs/files-backend.c: static void update_symref_reflog(struct files_ref_store *r
     +				    struct ref_lock *lock, const char *refname,
     +				    const char *target, const char *logmsg)
     +{
    ++	struct strbuf err = STRBUF_INIT;
     +	int ret;
     +
      	if (prefer_symlink_refs && !create_ref_symlink(lock, target)) {
    @@ refs/files-backend.c: static void update_symref_reflog(struct files_ref_store *r
     -	if (!fdopen_lock_file(&lock->lk, "w"))
     -		return error("unable to fdopen %s: %s",
     -			     get_lock_file_path(&lock->lk), strerror(errno));
    -+	ret = create_symref_lock(refs, lock, refname, target);
    ++	ret = create_symref_lock(refs, lock, refname, target, &err);
     +	if (!ret) {
     +		update_symref_reflog(refs, lock, refname, target, logmsg);
      
    @@ refs/files-backend.c: static void update_symref_reflog(struct files_ref_store *r
     +		if (commit_ref(lock) < 0)
     +			return error("unable to write symref for %s: %s", refname,
     +				     strerror(errno));
    ++	} else {
    ++		return error("%s", err.buf);
     +	}
      
     -	/* no error check; commit_ref will check ferror */
3:  901a586683 ! 3:  e0219ffd31 refs: support symrefs in 'reference-transaction' hook
    @@ refs.c: static int run_transaction_hook(struct ref_transaction *transaction,
     -			    oid_to_hex(&update->new_oid),
     -			    update->refname);
     +
    -+		if (update->flags & REF_HAVE_OLD && update->old_target)
    ++		if (!(update->flags & REF_HAVE_OLD))
    ++			strbuf_addf(&buf, "%s ", oid_to_hex(null_oid()));
    ++		else if (update->old_target)
     +			strbuf_addf(&buf, "ref:%s ", update->old_target);
     +		else
     +			strbuf_addf(&buf, "%s ", oid_to_hex(&update->old_oid));
     +
    -+		if (update->flags & REF_HAVE_NEW && update->new_target)
    ++		if (!(update->flags & REF_HAVE_NEW))
    ++			strbuf_addf(&buf, "%s ", oid_to_hex(null_oid()));
    ++		else if (update->new_target)
     +			strbuf_addf(&buf, "ref:%s ", update->new_target);
     +		else
     +			strbuf_addf(&buf, "%s ", oid_to_hex(&update->new_oid));
4:  6c97f6a660 ! 4:  b22c59c722 refs: add support for transactional symref updates
    @@ Commit message
         However, we never supported transactional updates of symrefs. Let's add
         support for symrefs in both the 'files' and the 'reftable' backend.
     
    -    Here, we add and use `ref_update_is_null_new_value()`, a helper function
    -    which is used to check if there is a new_value in a reference update.
    -    The new value could either be a symref target `new_target` or a OID
    -    `new_oid`.
    +    Here, we add and use `ref_update_has_null_new_value()`, a helper
    +    function which is used to check if there is a new_value in a reference
    +    update. The new value could either be a symref target `new_target` or a
    +    OID `new_oid`.
     
         With this, now transactional updates (verify, create, delete, update)
         can be used for:
    @@ Commit message
         This also allows us to expose this to users via new commands in
         'git-update-ref' in the future.
     
    -    We do not add reflog for dangling symref updates, because currently
    -    'git-symbolic-ref' doesn't add reflog for dangling symref updates and it
    -    would be best to keep this behavior consistent as we would move it to
    -    start using transaction based updates in the following commit.
    +    Note that a dangling symref update does not record a new reflog entry,
    +    which is unchanged before and after this commit.
     
         Signed-off-by: Karthik Nayak <karthik.188@gmail.com>
     
    @@ refs.c: struct ref_update *ref_transaction_add_update(
      	update->flags = flags;
      
     -	if (flags & REF_HAVE_NEW)
    -+	if (new_target)
    -+		update->new_target = xstrdup(new_target);
    -+	if (old_target)
    -+		update->old_target = xstrdup(old_target);
    -+	if (new_oid && flags & REF_HAVE_NEW)
    ++	update->new_target = xstrdup_or_null(new_target);
    ++	update->old_target = xstrdup_or_null(old_target);
    ++	if ((flags & REF_HAVE_NEW) && new_oid)
      		oidcpy(&update->new_oid, new_oid);
     -	if (flags & REF_HAVE_OLD)
    -+	if (old_oid && flags & REF_HAVE_OLD)
    ++	if ((flags & REF_HAVE_OLD) && old_oid)
      		oidcpy(&update->old_oid, old_oid);
     +
      	update->msg = normalize_reflog_message(msg);
    @@ refs.c: int copy_existing_ref(const char *oldref, const char *newref, const char
      	return refs_copy_existing_ref(get_main_ref_store(the_repository), oldref, newref, logmsg);
      }
     +
    -+int ref_update_is_null_new_value(struct ref_update *update)
    ++int ref_update_has_null_new_value(struct ref_update *update)
     +{
     +	return !update->new_target && is_null_oid(&update->new_oid);
     +}
    @@ refs/files-backend.c: static int lock_ref_for_update(struct files_ref_store *ref
      	files_assert_main_repository(refs, "lock_ref_for_update");
      
     -	if ((update->flags & REF_HAVE_NEW) && is_null_oid(&update->new_oid))
    -+	if ((update->flags & REF_HAVE_NEW) && ref_update_is_null_new_value(update))
    ++	if ((update->flags & REF_HAVE_NEW) && ref_update_has_null_new_value(update))
      		update->flags |= REF_DELETING;
      
      	if (head_ref) {
    @@ refs/files-backend.c: static int lock_ref_for_update(struct files_ref_store *ref
     -	    !(update->flags & REF_DELETING) &&
     -	    !(update->flags & REF_LOG_ONLY)) {
     +	if (update->new_target && !(update->flags & REF_LOG_ONLY)) {
    -+		if (create_symref_lock(refs, lock, update->refname, update->new_target)) {
    ++		if (create_symref_lock(refs, lock, update->refname, update->new_target, err)) {
     +			ret = TRANSACTION_GENERIC_ERROR;
     +			goto out;
     +		}
    @@ refs/files-backend.c: static int lock_ref_for_update(struct files_ref_store *ref
      		if (!(update->type & REF_ISSYMREF) &&
      		    oideq(&lock->old_oid, &update->new_oid)) {
      			/*
    +@@ refs/files-backend.c: static int files_transaction_prepare(struct ref_store *ref_store,
    + 	return ret;
    + }
    + 
    ++static int parse_and_write_reflog(struct files_ref_store *refs,
    ++				  struct ref_update *update,
    ++				  struct ref_lock *lock,
    ++				  struct strbuf *err)
    ++{
    ++	if (update->new_target) {
    ++		/*
    ++		 * We want to get the resolved OID for the target, to ensure
    ++		 * that the correct value is added to the reflog.
    ++		 */
    ++		if (!refs_resolve_ref_unsafe(&refs->base, update->new_target,
    ++					     RESOLVE_REF_READING,
    ++					     &update->new_oid, NULL)) {
    ++			/*
    ++			 * TODO: currently we skip creating reflogs for dangling
    ++			 * symref updates. It would be nice to capture this as
    ++			 * zero oid updates however.
    ++			 */
    ++			return 0;
    ++		}
    ++	}
    ++
    ++	if (files_log_ref_write(refs, lock->ref_name, &lock->old_oid,
    ++				&update->new_oid, update->msg, update->flags, err)) {
    ++		char *old_msg = strbuf_detach(err, NULL);
    ++
    ++		strbuf_addf(err, "cannot update the ref '%s': %s",
    ++			    lock->ref_name, old_msg);
    ++		free(old_msg);
    ++		unlock_ref(lock);
    ++		update->backend_data = NULL;
    ++		return -1;
    ++	}
    ++
    ++	return 0;
    ++}
    ++
    + static int files_transaction_finish(struct ref_store *ref_store,
    + 				    struct ref_transaction *transaction,
    + 				    struct strbuf *err)
     @@ refs/files-backend.c: static int files_transaction_finish(struct ref_store *ref_store,
      
      		if (update->flags & REF_NEEDS_COMMIT ||
    @@ refs/files-backend.c: static int files_transaction_finish(struct ref_store *ref_
     -						&update->new_oid,
     -						update->msg, update->flags,
     -						err)) {
    -+			int create_reflog = 1;
    -+
    -+			if (update->new_target) {
    -+				/*
    -+				 * We want to get the resolved OID for the target, to ensure
    -+				 * that the correct value is added to the reflog.
    -+				 */
    -+				if (!refs_resolve_ref_unsafe(&refs->base, update->new_target,
    -+							     RESOLVE_REF_READING, &update->new_oid, NULL)) {
    -+					/* for dangling symrefs we skip creating a reflog entry. */
    -+					create_reflog = 0;
    -+				}
    -+			}
    -+
    -+			if (create_reflog && files_log_ref_write(refs,
    -+								 lock->ref_name,
    -+								 &lock->old_oid,
    -+								 &update->new_oid,
    -+								 update->msg, update->flags,
    -+								 err)) {
    - 				char *old_msg = strbuf_detach(err, NULL);
    - 
    - 				strbuf_addf(err, "cannot update the ref '%s': %s",
    -@@ refs/files-backend.c: static int files_transaction_finish(struct ref_store *ref_store,
    +-				char *old_msg = strbuf_detach(err, NULL);
    +-
    +-				strbuf_addf(err, "cannot update the ref '%s': %s",
    +-					    lock->ref_name, old_msg);
    +-				free(old_msg);
    +-				unlock_ref(lock);
    +-				update->backend_data = NULL;
    ++			if (parse_and_write_reflog(refs, update, lock, err)) {
    + 				ret = TRANSACTION_GENERIC_ERROR;
      				goto cleanup;
      			}
      		}
    @@ refs/refs-internal.h: void base_ref_store_init(struct ref_store *refs, struct re
     + * takes into consideration that the update could be a regular
     + * ref or a symbolic ref.
     + */
    -+int ref_update_is_null_new_value(struct ref_update *update);
    ++int ref_update_has_null_new_value(struct ref_update *update);
     +
      #endif /* REFS_REFS_INTERNAL_H */
     
    @@ refs/reftable-backend.c: static int reftable_be_transaction_prepare(struct ref_s
      			 * when the reference in question doesn't exist.
      			 */
     -			 if (u->flags & REF_HAVE_NEW && !is_null_oid(&u->new_oid)) {
    -+			 if (u->flags & REF_HAVE_NEW && !ref_update_is_null_new_value(u)) {
    ++			 if ((u->flags & REF_HAVE_NEW) && !ref_update_has_null_new_value(u)) {
      				 ret = queue_transaction_update(refs, tx_data, u,
      								&current_oid, err);
      				 if (ret)
    @@ refs/reftable-backend.c: static int reftable_be_transaction_prepare(struct ref_s
     +				ret = -1;
     +				goto done;
     +			}
    -+		} else if (u->flags & REF_HAVE_OLD && !oideq(&current_oid, &u->old_oid)) {
    ++		} else if ((u->flags & REF_HAVE_OLD) && !oideq(&current_oid, &u->old_oid)) {
      			if (is_null_oid(&u->old_oid))
      				strbuf_addf(err, _("cannot lock ref '%s': "
      					    "reference already exists"),
    @@ refs/reftable-backend.c: static int write_transaction_table(struct reftable_writ
      		 *   the given ref.
      		 */
     -		if (u->flags & REF_HAVE_NEW && !(u->type & REF_ISSYMREF) && is_null_oid(&u->new_oid)) {
    -+		if (u->flags & REF_HAVE_NEW && !(u->type & REF_ISSYMREF) && ref_update_is_null_new_value(u)) {
    ++		if ((u->flags & REF_HAVE_NEW) && !(u->type & REF_ISSYMREF) && ref_update_has_null_new_value(u)) {
      			struct reftable_log_record log = {0};
      			struct reftable_iterator it = {0};
      
    @@ refs/reftable-backend.c: static int write_transaction_table(struct reftable_writ
      			    should_write_log(&arg->refs->base, u->refname))) {
      			struct reftable_log_record *log;
     +			int create_reflog = 1;
    ++
    ++			if (u->new_target) {
    ++				if (!refs_resolve_ref_unsafe(&arg->refs->base, u->new_target,
    ++							     RESOLVE_REF_READING, &u->new_oid, NULL)) {
    ++					/*
    ++					 * TODO: currently we skip creating reflogs for dangling
    ++					 * symref updates. It would be nice to capture this as
    ++					 * zero oid updates however.
    ++					 */
    ++					create_reflog = 0;
    ++				}
    ++			}
      
     -			ALLOC_GROW(logs, logs_nr + 1, logs_alloc);
     -			log = &logs[logs_nr++];
    @@ refs/reftable-backend.c: static int write_transaction_table(struct reftable_writ
     -			memcpy(log->value.update.old_hash, tx_update->current_oid.hash, GIT_MAX_RAWSZ);
     -			log->value.update.message =
     -				xstrndup(u->msg, arg->refs->write_options.block_size / 2);
    -+			if (u->new_target)
    -+				if (!refs_resolve_ref_unsafe(&arg->refs->base, u->new_target,
    -+							     RESOLVE_REF_READING, &u->new_oid, NULL))
    -+					/* for dangling symrefs we skip creating reflog */
    -+					create_reflog = 0;
    -+
     +			if (create_reflog) {
     +				ALLOC_GROW(logs, logs_nr + 1, logs_alloc);
     +				log = &logs[logs_nr++];
    @@ refs/reftable-backend.c: static int write_transaction_table(struct reftable_writ
      			continue;
      
     -		if (u->flags & REF_HAVE_NEW && is_null_oid(&u->new_oid)) {
    -+		if (u->flags & REF_HAVE_NEW && u->new_target) {
    ++		if (u->new_target) {
     +			struct reftable_ref_record ref = {
     +				.refname = (char *)u->refname,
     +				.value_type = REFTABLE_REF_SYMREF,
    @@ refs/reftable-backend.c: static int write_transaction_table(struct reftable_writ
     +			ret = reftable_writer_add_ref(writer, &ref);
     +			if (ret < 0)
     +				goto done;
    -+		} else if (u->flags & REF_HAVE_NEW && ref_update_is_null_new_value(u)) {
    ++		} else if ((u->flags & REF_HAVE_NEW) && ref_update_has_null_new_value(u)) {
      			struct reftable_ref_record ref = {
      				.refname = (char *)u->refname,
      				.update_index = ts,
5:  5b55406430 ! 5:  636bf5ce98 refs: use transaction in `refs_create_symref()`
    @@ Commit message
         target. To do this, it uses a ref-backend specific function
         `create_symref()`.
     
    -    In this previous commit, we introduce symref support in transactions.
    -    This means we can now use transactions to perform symref updates and not
    -    have to resort to `create_symref()`. Doing this allows us to remove and
    -    cleanup `create_symref()`, which we will do in the following commit.
    +    In the previous commits, we introduced symref support in transactions.
    +    This means we can now use transactions to perform symref updates and
    +    don't have to resort to `create_symref()`. Doing this allows us to
    +    remove and cleanup `create_symref()`, which we will do in the following
    +    commit.
     
         Modify the expected error message for a test in
    -    't/t0610-reftable-basics.sh', since the error is now thrown from the
    +    't/t0610-reftable-basics.sh', since the error is now thrown from
         'refs.c'. This is because in transactional updates, F/D conflicts are
         caught before we're in the reference backend.
     
    @@ t/t1416-ref-transaction-hooks.sh: test_expect_success 'interleaving hook calls s
     +	git symbolic-ref refs/heads/symref refs/heads/main &&
     +
     +	cat >expect <<-EOF &&
    -+		prepared
    -+		$ZERO_OID ref:refs/heads/main refs/heads/symref
    -+		committed
    -+		$ZERO_OID ref:refs/heads/main refs/heads/symref
    ++	prepared
    ++	$ZERO_OID ref:refs/heads/main refs/heads/symref
    ++	committed
    ++	$ZERO_OID ref:refs/heads/main refs/heads/symref
     +	EOF
     +
     +	test_cmp expect actual
6:  9e25816e68 = 6:  07fb23374f refs: rename `refs_create_symref()` to `refs_update_symref()`
7:  3836e25932 ! 7:  5c05813bcc refs: remove `create_symref` and associated dead code
    @@ Commit message
         transactions to perform symref updates. Earlier `refs_create_symref()`
         used `create_symref()` to do the same.
     
    -    This means, we can now remove `create_symref()` and any code associated
    -    with it which is no longer used. We remove `create_symref()` code from
    -    all the reference backends and also remove it entirely from the
    -    `ref_storage_be` struct.
    +    We can now remove `create_symref()` and any code associated with it
    +    which is no longer used. We remove `create_symref()` code from all the
    +    reference backends and also remove it entirely from the `ref_storage_be`
    +    struct.
     
         Signed-off-by: Karthik Nayak <karthik.188@gmail.com>
     
    @@ refs/files-backend.c: static int create_ref_symlink(struct ref_lock *lock, const
     -
      static int create_symref_lock(struct files_ref_store *refs,
      			      struct ref_lock *lock, const char *refname,
    - 			      const char *target)
    + 			      const char *target, struct strbuf *err)
     @@ refs/files-backend.c: static int create_symref_lock(struct files_ref_store *refs,
      	return 0;
      }
    @@ refs/files-backend.c: static int create_symref_lock(struct files_ref_store *refs
     -				    struct ref_lock *lock, const char *refname,
     -				    const char *target, const char *logmsg)
     -{
    +-	struct strbuf err = STRBUF_INIT;
     -	int ret;
     -
     -	if (prefer_symlink_refs && !create_ref_symlink(lock, target)) {
    @@ refs/files-backend.c: static int create_symref_lock(struct files_ref_store *refs
     -		return 0;
     -	}
     -
    --	ret = create_symref_lock(refs, lock, refname, target);
    +-	ret = create_symref_lock(refs, lock, refname, target, &err);
     -	if (!ret) {
     -		update_symref_reflog(refs, lock, refname, target, logmsg);
     -
     -		if (commit_ref(lock) < 0)
     -			return error("unable to write symref for %s: %s", refname,
     -				     strerror(errno));
    +-	} else {
    +-		return error("%s", err.buf);
     -	}
     -
     -	return ret;
Karthik Nayak (7):
  refs: accept symref values in `ref_transaction_update()`
  files-backend: extract out `create_symref_lock()`
  refs: support symrefs in 'reference-transaction' hook
  refs: add support for transactional symref updates
  refs: use transaction in `refs_create_symref()`
  refs: rename `refs_create_symref()` to `refs_update_symref()`
  refs: remove `create_symref` and associated dead code
 Documentation/githooks.txt       |  14 +-
 branch.c                         |   2 +-
 builtin/branch.c                 |   2 +-
 builtin/fast-import.c            |   5 +-
 builtin/fetch.c                  |   2 +-
 builtin/receive-pack.c           |   1 +
 builtin/replace.c                |   2 +-
 builtin/tag.c                    |   1 +
 builtin/update-ref.c             |   1 +
 builtin/worktree.c               |   2 +-
 refs.c                           |  89 +++++++++----
 refs.h                           |  20 ++-
 refs/debug.c                     |  13 --
 refs/files-backend.c             | 213 +++++++++++++++++++------------
 refs/packed-backend.c            |   1 -
 refs/refs-internal.h             |  26 +++-
 refs/reftable-backend.c          | 165 +++++++++---------------
 sequencer.c                      |   9 +-
 t/helper/test-ref-store.c        |   2 +-
 t/t0610-reftable-basics.sh       |   2 +-
 t/t1416-ref-transaction-hooks.sh |  23 ++++
 walker.c                         |   2 +-
 22 files changed, 351 insertions(+), 246 deletions(-)
-- 
2.43.GIT
Previous: Karthik NayakNext: Karthik Nayak
Message 148 of 194 in “update-ref: add support for update-symref option”
  1. 0/8 update-ref: add support for update-symref optionKarthik Nayak, Mar 30, 2024
  2. 1/8 files-backend: extract out `create_symref_lock`Karthik Nayak, Mar 30, 2024
  3. Patrick SteinhardtApr 2, 2024
  4. Karthik NayakApr 3, 2024
  5. 2/8 reftable-backend: extract out `write_symref_with_log`Karthik Nayak, Mar 30, 2024
  6. Patrick SteinhardtApr 2, 2024
  7. 3/8 reftable-backend: move `write_symref_with_log` upKarthik Nayak, Mar 30, 2024
  8. 4/8 refs: accept symref in `ref_transaction_add_update`Karthik Nayak, Mar 30, 2024
  9. 5/8 refs/files-backend: add support for symref updatesKarthik Nayak, Mar 30, 2024
  10. Patrick SteinhardtApr 2, 2024
  11. 6/8 refs/reftable-backend: add support for symref updatesKarthik Nayak, Mar 30, 2024
  12. Patrick SteinhardtApr 2, 2024
  13. 7/8 refs: add 'update-symref' command to 'update-ref'Karthik Nayak, Mar 30, 2024
  14. Junio C HamanoMar 31, 2024
  15. Chris TorekMar 31, 2024
  16. Junio C HamanoMar 31, 2024
  17. Junio C HamanoApr 1, 2024
  18. Patrick SteinhardtApr 2, 2024
  19. Junio C HamanoApr 2, 2024
  20. Patrick SteinhardtApr 9, 2024
  21. Karthik NayakApr 9, 2024
  22. Patrick SteinhardtApr 10, 2024
  23. Junio C HamanoApr 10, 2024
  24. Patrick SteinhardtApr 10, 2024
  25. Karthik NayakApr 1, 2024
  26. Karthik NayakApr 1, 2024
  27. Junio C HamanoApr 1, 2024
  28. Junio C HamanoApr 1, 2024
  29. Karthik NayakApr 1, 2024
  30. 8/8 refs: support symrefs in 'reference-transaction' hookKarthik Nayak, Mar 30, 2024
  31. Patrick SteinhardtApr 2, 2024
  32. 0/7 update-ref: add symref oriented commandsKarthik Nayak, Apr 12, 2024
  33. 1/7 refs: accept symref values in `ref_transaction[_add]_update`Karthik Nayak, Apr 12, 2024
  34. Christian CouderApr 18, 2024
  35. Karthik NayakApr 19, 2024
  36. Phillip WoodApr 18, 2024
  37. Patrick SteinhardtApr 19, 2024
  38. Karthik NayakApr 19, 2024
  39. phillip.wood123@gmail.comMay 4, 2024
  40. Patrick SteinhardtApr 19, 2024
  41. Karthik NayakApr 19, 2024
  42. Patrick SteinhardtApr 23, 2024
  43. Karthik NayakApr 23, 2024
  44. 2/7 update-ref: add support for symref-verifyKarthik Nayak, Apr 12, 2024
  45. Christian CouderApr 18, 2024
  46. Karthik NayakApr 19, 2024
  47. Patrick SteinhardtApr 19, 2024
  48. Karthik NayakApr 19, 2024
  49. 3/7 update-ref: add support for symref-deleteKarthik Nayak, Apr 12, 2024
  50. Christian CouderApr 18, 2024
  51. Karthik NayakApr 21, 2024
  52. Patrick SteinhardtApr 19, 2024
  53. Karthik NayakApr 21, 2024
  54. 4/7 files-backend: extract out `create_symref_lock`Karthik Nayak, Apr 12, 2024
  55. 5/7 update-ref: add support for symref-createKarthik Nayak, Apr 12, 2024
  56. Patrick SteinhardtApr 19, 2024
  57. Junio C HamanoApr 19, 2024
  58. Karthik NayakApr 21, 2024
  59. Karthik NayakApr 21, 2024
  60. Patrick SteinhardtApr 23, 2024
  61. Karthik NayakApr 23, 2024
  62. 7/7 refs: support symrefs in 'reference-transaction' hookKarthik Nayak, Apr 12, 2024
  63. 6/7 update-ref: add support for symref-updateKarthik Nayak, Apr 12, 2024
  64. Patrick SteinhardtApr 19, 2024
  65. Karthik NayakApr 21, 2024
  66. Patrick SteinhardtApr 23, 2024
  67. Karthik NayakApr 23, 2024
  68. Junio C HamanoApr 12, 2024
  69. Karthik NayakApr 12, 2024
  70. Christian CouderApr 18, 2024
  71. Karthik NayakApr 21, 2024
  72. Patrick SteinhardtApr 20, 2024
  73. Karthik NayakApr 21, 2024
  74. 0/8 refs: add symref support to 'git-update-ref'Karthik Nayak, Apr 23, 2024
  75. 1/8 refs: accept symref values in `ref_transaction[_add]_update`Karthik Nayak, Apr 23, 2024
  76. 2/8 update-ref: support parsing ref targets in `parse_next_oid`Karthik Nayak, Apr 23, 2024
  77. 3/8 files-backend: extract out `create_symref_lock`Karthik Nayak, Apr 23, 2024
  78. 4/8 update-ref: support symrefs in the verify commandKarthik Nayak, Apr 23, 2024
  79. 5/8 update-ref: support symrefs in the delete commandKarthik Nayak, Apr 23, 2024
  80. 6/8 update-ref: support symrefs in the create commandKarthik Nayak, Apr 23, 2024
  81. 7/8 update-ref: support symrefs in the update commandKarthik Nayak, Apr 23, 2024
  82. 8/8 ref: support symrefs in 'reference-transaction' hookKarthik Nayak, Apr 23, 2024
  83. Jeff KingApr 23, 2024
  84. Junio C HamanoApr 24, 2024
  85. Karthik NayakApr 24, 2024
  86. Patrick SteinhardtApr 25, 2024
  87. Karthik NayakApr 25, 2024
  88. Junio C HamanoApr 25, 2024
  89. Karthik NayakApr 25, 2024
  90. Junio C HamanoApr 25, 2024
  91. Karthik NayakApr 26, 2024
  92. Jeff KingApr 26, 2024
  93. Junio C HamanoApr 25, 2024
  94. Karthik NayakApr 25, 2024
  95. 0/7 add symref-* commands to 'git-update-ref --stdin'Karthik Nayak, Apr 26, 2024
  96. 1/7 refs: accept symref values in `ref_transaction[_add]_update`Karthik Nayak, Apr 26, 2024
  97. Junio C HamanoApr 26, 2024
  98. Jeff KingApr 26, 2024
  99. Patrick SteinhardtApr 29, 2024
  100. Jeff KingApr 29, 2024
  101. phillip.wood123@gmail.comApr 29, 2024
  102. phillip.wood123@gmail.comApr 29, 2024
  103. Junio C HamanoApr 29, 2024
  104. Jeff KingApr 30, 2024
  105. Jeff KingApr 30, 2024
  106. Karthik NayakApr 28, 2024
  107. Phillip WoodApr 29, 2024
  108. Karthik NayakApr 29, 2024
  109. 2/7 files-backend: extract out `create_symref_lock`Karthik Nayak, Apr 26, 2024
  110. Junio C HamanoApr 26, 2024
  111. Karthik NayakApr 28, 2024
  112. 3/7 update-ref: add support for 'symref-verify' commandKarthik Nayak, Apr 26, 2024
  113. Junio C HamanoApr 26, 2024
  114. Karthik NayakApr 28, 2024
  115. 4/7 update-ref: add support for 'symref-delete' commandKarthik Nayak, Apr 26, 2024
  116. 5/7 update-ref: add support for 'symref-create' commandKarthik Nayak, Apr 26, 2024
  117. 6/7 update-ref: add support for 'symref-update' commandKarthik Nayak, Apr 26, 2024
  118. 7/7 ref: support symrefs in 'reference-transaction' hookKarthik Nayak, Apr 26, 2024
  119. Karthik NayakApr 30, 2024
  120. 0/7 refs: add support for transactional symref updatesKarthik Nayak, May 1, 2024
  121. 1/7 refs: accept symref values in `ref_transaction_update()`Karthik Nayak, May 1, 2024
  122. 2/7 files-backend: extract out `create_symref_lock()`Karthik Nayak, May 1, 2024
  123. Junio C HamanoMay 1, 2024
  124. Patrick SteinhardtMay 2, 2024
  125. Karthik NayakMay 2, 2024
  126. Junio C HamanoMay 2, 2024
  127. 3/7 refs: support symrefs in 'reference-transaction' hookKarthik Nayak, May 1, 2024
  128. Junio C HamanoMay 1, 2024
  129. Karthik NayakMay 2, 2024
  130. 4/7 refs: add support for transactional symref updatesKarthik Nayak, May 1, 2024
  131. Junio C HamanoMay 1, 2024
  132. Karthik NayakMay 2, 2024
  133. Patrick SteinhardtMay 2, 2024
  134. Karthik NayakMay 2, 2024
  135. Junio C HamanoMay 2, 2024
  136. Junio C HamanoMay 2, 2024
  137. Junio C HamanoMay 2, 2024
  138. 5/7 refs: use transaction in `refs_create_symref()`Karthik Nayak, May 1, 2024
  139. Patrick SteinhardtMay 2, 2024
  140. 6/7 refs: rename `refs_create_symref()` to `refs_update_symref()`Karthik Nayak, May 1, 2024
  141. Patrick SteinhardtMay 2, 2024
  142. Karthik NayakMay 2, 2024
  143. 7/7 refs: remove `create_symref` and associated dead codeKarthik Nayak, May 1, 2024
  144. Patrick SteinhardtMay 2, 2024
  145. Junio C HamanoMay 2, 2024
  146. Junio C HamanoMay 2, 2024
  147. Karthik NayakMay 2, 2024
  148. 0/7 refs: add support for transactional symref updatesKarthik Nayak, May 3, 2024
  149. 1/7 refs: accept symref values in `ref_transaction_update()`Karthik Nayak, May 3, 2024
  150. Phillip WoodMay 4, 2024
  151. Karthik NayakMay 5, 2024
  152. phillip.wood123@gmail.comMay 5, 2024
  153. 2/7 files-backend: extract out `create_symref_lock()`Karthik Nayak, May 3, 2024
  154. 3/7 refs: support symrefs in 'reference-transaction' hookKarthik Nayak, May 3, 2024
  155. 4/7 refs: add support for transactional symref updatesKarthik Nayak, May 3, 2024
  156. Phillip WoodMay 5, 2024
  157. Karthik NayakMay 5, 2024
  158. Phillip WoodMay 6, 2024
  159. Karthik NayakMay 6, 2024
  160. Phillip WoodMay 6, 2024
  161. Phillip WoodMay 6, 2024
  162. Karthik NayakMay 6, 2024
  163. Phillip WoodMay 6, 2024
  164. 5/7 refs: use transaction in `refs_create_symref()`Karthik Nayak, May 3, 2024
  165. 6/7 refs: rename `refs_create_symref()` to `refs_update_symref()`Karthik Nayak, May 3, 2024
  166. 7/7 refs: remove `create_symref` and associated dead codeKarthik Nayak, May 3, 2024
  167. Junio C HamanoMay 3, 2024
  168. Karthik NayakMay 4, 2024
  169. Junio C HamanoMay 3, 2024
  170. Patrick SteinhardtMay 6, 2024
  171. 0/8 refs: add support for transactional symref updatesKarthik Nayak, May 7, 2024
  172. 1/8 refs: accept symref values in `ref_transaction_update()`Karthik Nayak, May 7, 2024
  173. 2/8 files-backend: extract out `create_symref_lock()`Karthik Nayak, May 7, 2024
  174. 3/8 refs: support symrefs in 'reference-transaction' hookKarthik Nayak, May 7, 2024
  175. 4/8 refs: move `original_update_refname` to 'refs.c'Karthik Nayak, May 7, 2024
  176. 5/8 refs: add support for transactional symref updatesKarthik Nayak, May 7, 2024
  177. 6/8 refs: use transaction in `refs_create_symref()`Karthik Nayak, May 7, 2024
  178. 7/8 refs: rename `refs_create_symref()` to `refs_update_symref()`Karthik Nayak, May 7, 2024
  179. 8/8 refs: remove `create_symref` and associated dead codeKarthik Nayak, May 7, 2024
  180. Junio C HamanoMay 7, 2024
  181. Junio C HamanoMay 7, 2024
  182. 0/8 refs: add support for transactional symref updatesKarthik Nayak, May 7, 2024
  183. 1/8 refs: accept symref values in `ref_transaction_update()`Karthik Nayak, May 7, 2024
  184. 2/8 files-backend: extract out `create_symref_lock()`Karthik Nayak, May 7, 2024
  185. 3/8 refs: support symrefs in 'reference-transaction' hookKarthik Nayak, May 7, 2024
  186. 4/8 refs: move `original_update_refname` to 'refs.c'Karthik Nayak, May 7, 2024
  187. 5/8 refs: add support for transactional symref updatesKarthik Nayak, May 7, 2024
  188. 6/8 refs: use transaction in `refs_create_symref()`Karthik Nayak, May 7, 2024
  189. 7/8 refs: rename `refs_create_symref()` to `refs_update_symref()`Karthik Nayak, May 7, 2024
  190. 8/8 refs: remove `create_symref` and associated dead codeKarthik Nayak, May 7, 2024
  191. phillip.wood123@gmail.comMay 7, 2024
  192. Junio C HamanoMay 7, 2024
  193. Karthik NayakMay 12, 2024
  194. Junio C HamanoMay 13, 2024

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.