reftable: wrong HEAD reflog when its target is updated in the same transaction

From
井上司 <hidden>
Date
2026-11-08 12:51:06
Hi,

With the reftable backend, if one transaction updates a branch and points
HEAD at it, the new HEAD reflog entry records the branch's old value. If
the branch is created in the same transaction, no HEAD reflog entry is
written at all. The files backend records the new value in both cases.

To reproduce on current master (fb255012ac):

  git init -q --ref-format=reftable repo && cd repo
  git commit -q --allow-empty -m one
  git commit -q --allow-empty -m two
  git branch y HEAD~
  printf '%s\n' start "update refs/heads/y $(git rev-parse HEAD)" \
          'option no-deref' 'symref-update HEAD refs/heads/y' commit |
  git update-ref -m test --stdin >/dev/null
  git log -1 --format='%h %s' HEAD
  git reflog -1 --format='%h %gs' HEAD

HEAD is at "two", but the "test" reflog entry points at "one". With
--ref-format=files it points at "two".

Using "create refs/heads/z <oid>" instead of updating y leaves HEAD's
reflog without a new entry.

I think the cause is write_transaction_table() in
refs/reftable-backend.c. For a symref update it gets the new oid for the
log record with refs_resolve_ref_unsafe() on new_target, which reads the
refs as they were before the transaction. So it sees the old value of y,
or no y at all, in which case the update is treated as a dangling symref
and the reflog entry is skipped.

I ran into this while looking at updating a new branch and HEAD in one
transaction for "git switch -c". Would taking the new oid from the
target's update in the same transaction, when there is one, be the right
fix? I can try to write a patch.

Thanks,
Tsukasa
Thread (2 messages) 2 messages, 2 authors, last reply 8m ago
Keyboard shortcuts
hback out one level
jnext message in thread / next series-diff position
kprevious message in thread / previous series-diff position
ldrill in
Escclose help / fold thread tree
?toggle this help