Git development
 help / color / mirror / Atom feed
* [BUG] reference-transaction reports zero OIDs for branch and tag deletion
@ 2026-09-19 13:34 Maciej Ciemborowicz
  2026-09-19 14:59 ` D. Ben Knoble
  0 siblings, 1 reply; 53+ messages in thread
From: Maciej Ciemborowicz @ 2026-09-19 13:34 UTC (permalink / raw)
  To: git

Since Git 2.31, the reference-transaction hook receives all-zero old and
new object IDs when a branch or tag is deleted with a high-level command.

For example, `git branch -d topic` produces:

    0000000000000000000000000000000000000000 \
    0000000000000000000000000000000000000000 \
    refs/heads/topic

The same happens with `git branch -D`, `git tag -d`, and deletion of a
remote-tracking ref by `git remote prune`.

Git 2.28 through 2.30 reported the previous object ID followed by the
all-zero object ID. Starting with Git 2.31, that information is lost.
The behavior is still present in Git 2.55 with both the files and
reftable backends.

A direct deletion with:

    git update-ref -d refs/heads/topic "$old_oid"

continues to report the useful payload:

    <old-oid> 0000000000000000000000000000000000000000 refs/heads/topic

Minimal reproducer:

    #!/bin/sh
    set -eu

    root=$(mktemp -d)
    trap 'rm -rf "$root"' EXIT

    repo=$root/repo
    hooks=$root/hooks
    log=$root/transactions

    git init -q "$repo"
    git -C "$repo" config user.name Reproducer
    git -C "$repo" config user.email repro@example.com
    git -C "$repo" commit --allow-empty -qm initial

    git -C "$repo" branch topic
    git -C "$repo" tag v1

    mkdir "$hooks"
    cat >"$hooks/reference-transaction" <<'HOOK'
    #!/bin/sh
    printf '%s\n' "--- $1" >>"$HOOK_LOG"
    cat >>"$HOOK_LOG"
    HOOK
    chmod +x "$hooks/reference-transaction"

    git -C "$repo" config core.hooksPath "$hooks"
    export HOOK_LOG=$log
    : >"$log"

    git -C "$repo" branch -d topic
    git -C "$repo" tag -d v1

    cat "$log"

Actual output for the committed transactions is equivalent to:

    0000000000000000000000000000000000000000 \
    0000000000000000000000000000000000000000 \
    refs/heads/topic
    0000000000000000000000000000000000000000 \
    0000000000000000000000000000000000000000 \
    refs/tags/v1

I expected:

    <old-oid> 0000000000000000000000000000000000000000 refs/heads/topic
    <old-oid> 0000000000000000000000000000000000000000 refs/tags/v1

I understand that the reference-transaction documentation permits an
all-zero old value when a ref is force-updated without checking its
current value. However, `git branch -d` is a safety-checked deletion,
Git has already resolved the branch being deleted, and Git 2.28–2.30
provided its old object ID.

Was this loss of information intentional? If not, could the previous
object ID be restored for these deletion paths? If it is intentional,
the documentation may need to clarify that high-level deletion commands
can provide a zero-to-zero record.

The behavior was tested across Git 2.28–2.55. The compatibility results
and test implementation are available here:

https://github.com/ciembor/git-hooks-ext/blob/v0.2.0/tests/compat/README.md
https://github.com/ciembor/git-hooks-ext/blob/v0.2.0/tests/compat/e2e.sh

Thanks,
Maciej Ciemborowicz

^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [BUG] reference-transaction hook misses destination of git branch -m
@ 2026-09-19 20:52 Karthik Nayak
  2026-09-23 12:49 ` [PATCH v4 0/3] refs: report old OIDs for batched deletions Maciej Ciemborowicz
  0 siblings, 1 reply; 53+ messages in thread
From: Karthik Nayak @ 2026-09-19 20:52 UTC (permalink / raw)
  To: Maciej Ciemborowicz, git

[-- Attachment #1: Type: text/plain, Size: 2640 bytes --]

Maciej Ciemborowicz <maciej.ciemborowicz@gmail.com> writes:

> Hello,
>
> `git branch -m old new` changes refs/heads/old into refs/heads/new,
> but the reference-transaction hook does not report both ref changes.
>

My understanding without digging too deep is that both 'copy' and
'rename' do not use a transaction, as such they don't trigger the
'reference-transaction' hook. This is definitely absurd, since we would
expect that all reference operations should use the transaction and
trigger the hook.

> Observed with Git 2.55:
>
> * files backend: the hook reports deletion of refs/heads/old, but
>   does not report creation of refs/heads/new;

Yeah, because the files backend calls `refs_delete_ref()` on the old
reference which is done within a transaction.

> * reftable backend: the hook reports no usable rename payload.

Reftable doesn't call `refs_delete_ref()` and simply writes a TOMBSTONE
entry to delete the old reference.

> The equivalent atomic operation performed with `git update-ref --stdin`
> reports both updates correctly.
>

By equivalent atomic operation do you a 'delete' and 'create' command?

> I expected the transaction to include:
>
>     <oid> <zero> refs/heads/old
>     <zero> <oid> refs/heads/new
>
> Minimal reproducer:
>
>     #!/bin/sh
>     set -eu
>
>     format=${1:-files}
>     root=$(mktemp -d)
>     trap 'rm -rf "$root"' EXIT
>
>     repo=$root/repo
>     hooks=$root/hooks
>     log=$root/transactions
>
>     git init -q --ref-format="$format" "$repo"
>     git -C "$repo" config user.name Reproducer
>     git -C "$repo" config user.email repro@example.com
>     git -C "$repo" commit --allow-empty -qm initial
>     git -C "$repo" branch old
>
>     mkdir "$hooks"
>     cat >"$hooks/reference-transaction" <<'HOOK'
>     #!/bin/sh
>     printf '%s\n' "--- $1" >>"$HOOK_LOG"
>     cat >>"$HOOK_LOG"
>     HOOK
>     chmod +x "$hooks/reference-transaction"
>
>     git -C "$repo" config core.hooksPath "$hooks"
>     export HOOK_LOG=$log
>     : >"$log"
>
>     git -C "$repo" branch -m old new
>     cat "$log"
>
> The behavior was also tested across Git 2.28–2.55:
> https://github.com/ciembor/git-hooks-ext/blob/v0.2.0/tests/compat/README.md
>
> The reference-transaction documentation says that the hook is invoked by
> Git commands performing reference updates. A branch rename changes two refs,
> but the destination update is not visible to the hook.
>

Either ways, I think we should fix this, I could have a look if you
aren't submitting a patch yourself :)

> Thanks,
> Maciej Ciemborowicz

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 690 bytes --]

^ permalink raw reply	[flat|nested] 53+ messages in thread

end of thread, other threads:[~2026-10-01 17:37 UTC | newest]

Thread overview: 53+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-19 13:34 [BUG] reference-transaction reports zero OIDs for branch and tag deletion Maciej Ciemborowicz
2026-09-19 14:59 ` D. Ben Knoble
2026-09-19 15:42   ` Maciej Ciemborowicz
2026-09-19 20:11     ` [PATCH 0/3] refs: report old OIDs for batched deletions Maciej Ciemborowicz
2026-09-19 20:11       ` [PATCH 1/3] refs: allow callers to supply old OIDs for batch deletion Maciej Ciemborowicz
2026-09-19 20:41         ` Karthik Nayak
2026-09-20 10:38           ` Maciej Ciemborowicz
2026-09-20 10:54           ` [PATCH v2 0/3] refs: report old OIDs for batched deletions Maciej Ciemborowicz
2026-09-20 10:54             ` [PATCH v2 1/3] refs: allow callers to supply old OIDs for batch deletion Maciej Ciemborowicz
2026-09-21 13:12               ` Karthik Nayak
2026-09-21 23:55               ` Junio C Hamano
2026-09-20 10:54             ` [PATCH v2 2/3] branch, tag: retain old OIDs in batched deletions Maciej Ciemborowicz
2026-09-21 13:19               ` Karthik Nayak
2026-09-20 10:54             ` [PATCH v2 3/3] fetch, remote: retain old OIDs when pruning refs Maciej Ciemborowicz
2026-09-21 13:56               ` Karthik Nayak
2026-09-21 13:57             ` [PATCH v2 0/3] refs: report old OIDs for batched deletions Karthik Nayak
2026-09-21 20:01               ` Maciej Ciemborowicz
2026-09-22 12:26             ` [PATCH v3 " Maciej Ciemborowicz
2026-09-22 12:26               ` [PATCH v3 1/3] refs: allow callers to supply old OIDs for batch deletion Maciej Ciemborowicz
2026-09-22 18:55                 ` Junio C Hamano
2026-09-22 19:21                   ` Maciej Ciemborowicz
2026-09-22 23:31                     ` Junio C Hamano
2026-09-22 12:26               ` [PATCH v3 2/3] branch, tag: retain old OIDs in batched deletions Maciej Ciemborowicz
2026-09-22 12:26               ` [PATCH v3 3/3] fetch, remote: retain old OIDs when pruning refs Maciej Ciemborowicz
2026-09-22 19:16                 ` Junio C Hamano
2026-09-22 22:29               ` [PATCH v4 0/3] refs: report old OIDs for batched deletions Maciej Ciemborowicz
2026-09-22 22:31                 ` [PATCH v4 1/3] refs: allow callers to supply old OIDs for batch deletion Maciej Ciemborowicz
2026-09-22 22:31                 ` [PATCH v4 2/3] branch, tag: retain old OIDs in batched deletions Maciej Ciemborowicz
2026-09-22 22:31                 ` [PATCH v4 3/3] fetch, remote: retain old OIDs when pruning refs Maciej Ciemborowicz
2026-09-23 20:03                   ` Junio C Hamano
2026-09-23 21:02                     ` Maciej Ciemborowicz
2026-09-23 21:04                 ` [PATCH v5 0/3] refs: report old OIDs for batched deletions Maciej Ciemborowicz
2026-09-23 21:04                   ` [PATCH v5 1/3] refs: allow callers to supply old OIDs for batch deletion Maciej Ciemborowicz
2026-09-24 10:04                     ` Karthik Nayak
2026-09-24 16:34                       ` Junio C Hamano
2026-09-24 19:43                       ` Maciej Ciemborowicz
2026-09-24 11:07                     ` Patrick Steinhardt
2026-09-24 16:45                       ` Junio C Hamano
2026-09-24 20:13                         ` Maciej Ciemborowicz
2026-09-28  6:44                           ` Patrick Steinhardt
2026-09-28  6:43                         ` Patrick Steinhardt
2026-09-24 19:56                       ` Maciej Ciemborowicz
2026-09-23 21:04                   ` [PATCH v5 2/3] branch, tag: retain old OIDs in batched deletions Maciej Ciemborowicz
2026-09-24 11:08                     ` Patrick Steinhardt
2026-09-23 21:04                   ` [PATCH v5 3/3] fetch, remote: retain old OIDs when pruning refs Maciej Ciemborowicz
2026-09-23 21:55                   ` [PATCH v5 0/3] refs: report old OIDs for batched deletions Junio C Hamano
2026-09-24 22:33                   ` [PATCH v6 0/1] refs: report old values to transaction hooks Maciej Ciemborowicz
2026-09-24 22:33                     ` [PATCH v6 1/1] " Maciej Ciemborowicz
2026-09-30  3:11                       ` Maciej Ciemborowicz
2026-10-01 17:37                         ` Maciej Ciemborowicz
2026-09-19 20:11       ` [PATCH 2/3] branch, tag: retain old OIDs in batched deletions Maciej Ciemborowicz
2026-09-19 20:11       ` [PATCH 3/3] fetch, remote: retain old OIDs when pruning refs Maciej Ciemborowicz
  -- strict thread matches above, loose matches on Subject: below --
2026-09-19 20:52 [BUG] reference-transaction hook misses destination of git branch -m Karthik Nayak
2026-09-23 12:49 ` [PATCH v4 0/3] refs: report old OIDs for batched deletions Maciej Ciemborowicz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox