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

reference-transaction regression in 2.36.0-rc1

From
Bryan Turner <bturner@atlassian.com>
Date
Apr 12, 2022, 09:20 UTC
Message-ID
<CAGyf7-GYYA2DOnAVYW--=QEc2WjSHzUhp2OQyuyOr3EOtFDm6g@mail.gmail.com>

It looks like Git 2.36.0-rc1 includes the changes to eliminate/pare back reference transactions being raised independently for loose and packed refs. It's a great improvement, and one we're very grateful for.

It looks like there's a regression, though. When deleting a ref that _only_ exists in packed-refs, by the time the "prepared" callback is raised the ref has already been deleted completely. Normally when "prepared" is raised the ref is still present. The ref still being present is important to us, since the reference-transaction hook is frequently not passed any previous hash; we resolve the ref during "prepared", if the previous hash is the null SHA1, so that we can correctly note what the tip commit was when the ref was deleted.

Here's a reproduction: git init ref-tx cd ref-tx git commit -m "Initial commit" --allow-empty git branch to-delete git pack-refs --all echo 'echo "Callback: $1"; cat; git rev-parse refs/heads/to-delete --; exit 0' > .git/hooks/reference-transaction chmod +x .git/hooks/reference-transaction git branch -d to-delete

If you _skip_ the pack-refs, you'll get output like this:
$ git branch -d to-delete
Callback: prepared
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000 refs/heads/to-delete
aab0f2e707acd1b84e81f4e4b833ff0d9ee7cc50
--
Callback: committed
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000 refs/heads/to-delete
fatal: bad revision 'refs/heads/to-delete'
Deleted branch to-delete (was aab0f2e).

You can see that, during "prepared", rev-parse returns aab0f2e7 and after "committed" the ref no longer exists.

With the pack-refs, you get this:
$ git branch -d to-delete
Callback: prepared
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000 refs/heads/to-delete
fatal: bad revision 'refs/heads/to-delete'
Callback: committed
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000 refs/heads/to-delete
fatal: bad revision 'refs/heads/to-delete'
Deleted branch to-delete (was aab0f2e).

In both cases, the reference-transaction isn't invoked with the hash of the ref being deleted (even though Git clearly _knows_ it, since it outputs it itself afterward), but if the ref exists loose we can at least find out what it was.

Contrast this to Git 2.35.1:
$ git branch -d to-delete
Callback: prepared
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000 refs/heads/to-delete
aab0f2e707acd1b84e81f4e4b833ff0d9ee7cc50
--
Callback: committed
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000 refs/heads/to-delete
fatal: bad revision 'refs/heads/to-delete'
Callback: aborted
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000 refs/heads/to-delete
fatal: bad revision 'refs/heads/to-delete'
Callback: prepared
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000 refs/heads/to-delete
fatal: bad revision 'refs/heads/to-delete'
Callback: committed
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000 refs/heads/to-delete
fatal: bad revision 'refs/heads/to-delete'
Deleted branch to-delete (was aab0f2e).

With the reference-transactions for both packed and loose, when the packed reference transaction runs we can still see the commit hash.

It seems like Git should either:
- Provide the PREPARED callback before _either_ packed or loose refs
are updated, or
- Provide the actual SHA as the old hash when invoking the hook (which
would be great because it would save us the overhead of resolving it
ourselves)

It's probably complicated to do either of those, but without one or the other this change makes it very difficult to replicate updates reliably via reference-transaction because we can't be 100% sure we're applying the same deletion on replicas without knowing the old hash.

Best regards, Bryan Turner

(Apologies for the double-send; forgot to enable plain text mode the first time.)

Next: Bryan Turner
Message 1 of 14 in “reference-transaction regression in 2.36.0-rc1”
  1. Bryan TurnerApr 12, 2022
  2. Bryan TurnerApr 12, 2022
  3. Ævar Arnfjörð BjarmasonApr 13, 2022
  4. René ScharfeApr 13, 2022
  5. Junio C HamanoApr 13, 2022
  6. Junio C HamanoApr 13, 2022
  7. Bryan TurnerApr 13, 2022
  8. Junio C HamanoApr 13, 2022
  9. Junio C HamanoApr 13, 2022
  10. Bryan TurnerApr 15, 2022
  11. Ævar Arnfjörð BjarmasonApr 15, 2022
  12. Junio C HamanoApr 15, 2022
  13. Patrick SteinhardtApr 27, 2022
  14. Patrick SteinhardtMay 2, 2022

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.