From: Karthik Nayak <karthik.188@xxxxxxxxx> The 'git-update-ref(1)' command allows transactional reference updates. But currently only supports regular reference updates. Meaning, if one wants to update HEAD (symbolic ref) in a transaction, there is no tool to do so. One option to obtain transactional updates for the HEAD ref is to manually create the HEAD.lock file and commit. This is intrusive, where the user needs to mimic internal git behavior. Also, this only works when using the files backend. At GitLab, we've been using the manual process till date, to allow users to set and change their default branch. But with the introduction of reftables as a reference backend, this becomes a necessity to be solved within git. This patch series goes about introducing a set of commands symref-{create,verify,delete,update} to work with symrefs complimenting the existing commands for the regular refs within 'git-update-ref(1)'. The 'symref-verify' command can be used to verify if a symref exists and its existing value. The 'symref-create' command can be used to create a new symref. The 'symref-delete' command can be used to delete an existing symref while optionally checking its existing value. The 'symref-update' command can be used to update a symref, create a symref, delete a symref or even convert an existing regular ref to a symref. Wherein like the regular 'update' command, the zero OID can be used to create/delete a symref. V1 of the patch series can be found here: https://lore.kernel.org/git/20240330224623.579457-1-knayak@xxxxxxxxxx/ I'm not adding a range diff here, cause I redid the whole series, things which have changed: 1. The earlier series simply propagated a 'symref_target' and only supported the 'symref-update' command, without checks for existing values and such. Now we support the entire fleet of commands with support for checking old_values. 2. The flow is now changedc to send an old_ref, new_ref pair in supplement to the existing old_oid, new_oid pair to the reference backends. This allows the backends to simply do a combination of changes based on what values are set. This allows us to do symref-update's where we change a regular ref to a symref while also validating its old OID. 3. I added a lot more tests to cover reflog checks and also '-z' input. 4. The entered <old-ref> and <new-ref> values are checked within update-ref, to ensure we don't create dangling refs. This could be extended in the future with a flag, maybe "REF_ALLOW_DANGLING_SYMREF" and a corresponding option within update-ref. 5. Removed some commits where reftable backend code was reused for symref creation. This actually caused issues since the reused code also created a reflog along with the symref but we should defer reflog creations only after all ref creations have taken place. There is a bit of DRY here, but I think overall its still much cleaner. Thanks all for the review and discussion in the previous version. Patrick, I did incorporate the changes you suggested, but I just noticed that I didn't reply to your emails. Karthik Nayak (7): refs: accept symref values in `ref_transaction[_add]_update` update-ref: add support for symref-verify update-ref: add support for symref-delete files-backend: extract out `create_symref_lock` update-ref: add support for symref-create update-ref: add support for symref-update refs: support symrefs in 'reference-transaction' hook Documentation/git-update-ref.txt | 25 +++ Documentation/githooks.txt | 13 +- branch.c | 2 +- builtin/clone.c | 2 +- builtin/fast-import.c | 5 +- builtin/fetch.c | 4 +- builtin/receive-pack.c | 4 +- builtin/replace.c | 2 +- builtin/tag.c | 1 + builtin/update-ref.c | 202 +++++++++++++++++-- refs.c | 74 +++++-- refs.h | 15 +- refs/files-backend.c | 143 +++++++++++--- refs/refs-internal.h | 21 ++ refs/reftable-backend.c | 51 ++++- sequencer.c | 9 +- t/t0600-reffiles-backend.sh | 32 ++++ t/t1400-update-ref.sh | 320 ++++++++++++++++++++++++++++++- t/t1416-ref-transaction-hooks.sh | 41 ++++ walker.c | 2 +- 20 files changed, 886 insertions(+), 82 deletions(-) -- 2.43.GIT