Neko

Converting shallow Git bundles into normal repositories

Let’s say you have a shallow Git bundle, i.e., not all referenced objects are present. How do you convert it into a normal shallow repository?

  1. Initialize the target as a bare-repo with your desired object-format.
    git init --bare --object-format=sha1 target.git && cd target.git

  2. Find the start of the pack in each bundle (version 2 packs starts with 5041 434b 0000 0002). In my case it’s byte offset 77.

  3. Extract and index the packfile, creating the .idx and .rev.
    tail -c +77 ../source.bundle | git index-pack --stdin

  4. Extract the ref OID and ref name from the bundle.
    oid="$(git bundle list-heads source.bundle | awk '{print $1}')"
    ref="$(git bundle list-heads source.bundle | awk '{print $2}')"

  5. Set the ref to the OID, and set HEAD to the ref.
    git update-ref "$ref" "$oid"
    git symbolic-ref HEAD "$ref"

  6. Indicate the shallow commit. You should use the oldest commit here. My example has a depth of 1, so I can just use the head.
    printf '%s\n' "$oid" > shallow

  7. git fsck --full, or whatever.

I think the bundle format should gain the ability to communicate shallowness. Might take it upstream when I have the time.