Thread (2 messages) flat view 2 messages, 2 authors, 11d ago

[BUG] git bundle create with bitmaps omits tree required by advertised ref

From: Peter Elmers <hidden>
Date: 2026-09-08 08:23:50

What did you do before the bug happened? (Steps to reproduce your issue)

I created two sibling commits with the same root tree, stored one at a local
branch and the other at a remote-tracking ref, wrote a pack bitmap, and created
a bundle that included the local branch while excluding the remote-tracking
ref.

Adding `-c pack.useBitmaps=false` appears to fix the issue.

The following script reproduces the issue:

#!/bin/sh
set -eu

repro_dir=$(mktemp -d)
source_repo="$repro_dir/source.git"
recipient_repo="$repro_dir/recipient.git"

git init -q --bare -b main "$source_repo"
git -C "$source_repo" config user.name A
git -C "$source_repo" config user.email a@example.com

empty_tree=$(git -C "$source_repo" mktree </dev/null)
base=$(printf 'base\n' | git -C "$source_repo" commit-tree "$empty_tree")
git -C "$source_repo" update-ref refs/heads/main "$base"
git clone -q --bare "$source_repo" "$recipient_repo"

blob=$(printf 'change\n' | git -C "$source_repo" hash-object -w --stdin)
shared_tree=$(printf '100644 blob %s\tfile\n' "$blob" |
  git -C "$source_repo" mktree)
remote_tip=$(printf 'original\n' |
  git -C "$source_repo" commit-tree "$shared_tree" -p "$base")
local_tip=$(printf 'rewritten\n' |
  git -C "$source_repo" commit-tree "$shared_tree" -p "$base")

git -C "$source_repo" update-ref refs/heads/feature "$local_tip"
git -C "$source_repo" update-ref refs/remotes/origin/feature "$remote_tip"
git -C "$source_repo" repack -q -ad --write-bitmap-index
git -C "$source_repo" bundle create "$repro_dir/broken.bundle" \
  feature ^refs/remotes/origin/feature

git -C "$recipient_repo" bundle verify "$repro_dir/broken.bundle"
git -C "$recipient_repo" bundle unbundle "$repro_dir/broken.bundle"
git -C "$recipient_repo" cat-file -e "$local_tip^{tree}"

The resulting commit and object topology is:

                         refs/remotes/origin/feature (excluded)
                                         |
                                     remote_tip
                                    /          \
                            parent /            \ tree
                                  /              \
                              base                shared_tree
                                  \              /
                            parent \            / tree
                                    \          /
                                     local_tip
                                         |
                              refs/heads/feature (advertised)

Both tip commits have `base` as their parent and `shared_tree` as their root
tree. The bundle advertises `local_tip` and excludes `remote_tip`.

What did you expect to happen? (Expected behavior)

After `git bundle verify` confirms that the recipient has every declared
prerequisite and `git bundle unbundle` succeeds, every object required by the
advertised `feature` commit should be available. The final `git cat-file`
command should exit successfully.

What happened instead? (Actual behavior)

`git bundle verify` reports that the bundle is okay and `git bundle unbundle`
succeeds, but the final command (cat-file) exits 128:

fatal: Not a valid object name <local-tip>^{tree}

The advertised local commit object is present, but its root tree is absent.

What's different between what you expected and what actually happened?

The bitmap-backed bundle omits an object required by an advertised ref without
declaring the excluded sibling commit as a prerequisite. A recipient containing
all declared prerequisites can therefore accept the bundle but cannot traverse
or check out the advertised commit.

Anything else you want to add:

Adding `-c pack.useBitmaps=false` to `git bundle create` makes the final
`git cat-file` command succeed.

`pack.useBitmapBoundaryTraversal=true` did not prevent the omission in a
separate run of the same commit topology.

So it looks like a bitmap format bug.

Relevant documentation:

https://git-scm.com/docs/git-config#Documentation/git-config.txt-packuseBitmaps
https://git-scm.com/docs/git-config#Documentation/git-config.txt-packuseBitmapBoundaryTraversal
https://git-scm.com/docs/git-bundle#_object_prerequisites

[System Info]
git version:
git version 2.54.0
cpu: x86_64
no commit associated with this build
sizeof-long: 8
sizeof-size_t: 8
shell-path: /bin/sh
rust: disabled
SHA-1: SHA1_DC
SHA-256: SHA256_BLK
default-ref-format: files
default-hash: sha1
uname: Linux 7.0.0-1012-aws #12~24.04.1-Ubuntu SMP PREEMPT Wed Aug 12
14:00:57 UTC 2026 x86_64
compiler info: gnuc: 9.4
libc info: glibc: 2.39
$SHELL (typically, interactive shell): /usr/bin/zsh
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help