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

Re: Bug report: Strange behavior with `git gc` and `reference-transaction` hook

From
Bryan Turner <bturner@atlassian.com>
Date
Nov 18, 2021, 00:52 UTC
Message-ID
<CAGyf7-FoRyVtQHa2ETQtRA6fD7x0GDhKVPg+eAajhgPNrsw_OQ@mail.gmail.com>
In-Reply-To
<CAKjfCeBcuYC3OXRVtxxDGWRGOxC38Fb7CNuSh_dMmxpGVip_9Q@mail.gmail.com>
On Wed, Nov 17, 2021 at 4:42 PM Waleed Khan <me@waleedkhan.name> wrote:
Show 54 quoted lines
>
> Hi all,
>
> I'm seeing unusual behavior on Git built from source at
> cd3e606211bb1cf8bc57f7d76bab98cc17a150bc, but which appears to extend
> back to Git v2.29.
>
> This is a repro script:
>
> ```
> #!/bin/sh
>
> temp_dir=$(mktemp -d)
> echo "git dir is: $temp_dir"
> mkdir -p "$temp_dir"
> trap "rm -rf $temp_dir" EXIT
>
> cd "$temp_dir" || exit 1
> git init -q
> date='Thu, 07 Apr 2005 22:13:13 +0200'
> GIT_AUTHOR_DATE="$date" GIT_COMMITTER_DATE="$date" git commit -q
> --allow-empty -m 'Initial commit'
>
> mkdir -p '.git/hooks'
> cat >.git/hooks/reference-transaction <<'EOT'
> #!/bin/sh
>
> [[ "$1" != 'committed' ]] && exit 0
> echo 'New reference-transaction invocation'
>
> while read old new ref; do
>   echo "  old: $old, new: $new, ref: $ref"
> done
> EOT
> chmod +x .git/hooks/reference-transaction
>
> git gc --prune=now -q
> git show-ref refs/heads/master
> ```
>
> And this is the output it produces:
>
> ```
> git dir is: /var/folders/gn/gdp9z_g968b9nx7c9lvgy8y00000gp/T/tmp.b3Jc6qnb
> New reference-transaction invocation
>   old: 0000000000000000000000000000000000000000, new:
> e197d18c017d4038418be8b1cd38f4503e289165, ref: refs/heads/master
> New reference-transaction invocation
>   old: e197d18c017d4038418be8b1cd38f4503e289165, new:
> 0000000000000000000000000000000000000000, ref: refs/heads/master
> e197d18c017d4038418be8b1cd38f4503e289165 refs/heads/master
> ```
>
> These hooks are invoked a few milliseconds one after another.

There are two built-in "ref backends" that Git uses out of the box: A packed backend, which manages the "packed-refs" file, and a loose backend, which manages other files under "$GIT_DIR/refs". What you're seeing is a reference transaction for the packed backend which is adding the new value for "refs/heads/master" to "packed-refs" (packed backend reference-transactions rarely, if ever, include an actual old hash, as far as I can tell), and then a second reference transaction for the loose backend to delete the loose "refs/heads/master" file, now that it's packed.

Show 8 quoted lines
>
> The expected behavior would be that the latest reference transaction
> hook refers to the state of the references on disk. That is, either
> `master` should point to 0 (be deleted), or it should have said that
> `master` pointed to `e197d1`.
>
> But if we actually examine `master`, it's set to `e197d1`, just as you
> would expect. The GC should have been a no-op overall.

One of the subtasks of "git gc" is "git pack-refs". If you inspect in more detail, I suspect you'll find that "refs/heads/master" was loose before "git gc" ran (as in, there was a file "$GIT_DIR/refs/heads/master") and "packed-refs" either didn't have a "refs/heads/master" entry or had a different hash. (Loose refs always "win" over packed, since ref updates only write loose refs.)

Hope this helps, Bryan Turner

>
> Best,
> Waleed
Previous: Waleed KhanNext: Jeff King
Message 2 of 5 in “Bug report: Strange behavior with `git gc` and `reference-transaction` hook”
  1. Waleed KhanNov 18, 2021
  2. Bryan TurnerNov 18, 2021
  3. Jeff KingNov 18, 2021
  4. Patrick SteinhardtDec 7, 2021
  5. Bryan TurnerNov 18, 2021

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.