Subject: Re: Some feedback on 'git clone create'

From: Patrick Steinhardt <[email-masked]>
Date: Thu, 5 Dec 2024 09:38:03 +0100

On Wed, Dec 04, 2024 at 05:19:53PM -0600, Justin Tobler wrote:
> On 24/12/04 05:28AM, Sainan wrote:
> > Hi, I hope this email finds you well.
> > 
> > I think Git bundles/packfiles are an exceptional compression format, but I find there are some rough edges with the tool to create them:
> > 
> > 1. There is no way to specify that you want a shallow bundle, instead you are only able to a) pack the entire tree at a given head or b) pack new/updated objects in a specified range. Anecdotally, this could store data in ~67% of the size of an equivalent .zip file.
> 
> You can create an incremental bundle covering a specified range.
> Something like the following example might help you achieve what you are
> looking for:
> 
>   $ git bundle create inc.bundle main~10..main

Yup. The thing that might not be immediately obvious is that
git-bundle(1) accepts git-rev-list(1) arguments, so you can influence
what is and isn't included via that. You can for example even generate
partial bundles without blobs:

    $ git bundle create partial.bundle main~10..main \
        --filter=blob:none

What you can do with the resulting bundle might be a different story.

> > 2. It seems that when specifiying a commit hash, it raises an error:
> > $ git bundle create repo.bundle $(git rev-list HEAD | head -n 1)
> > > fatal: Refusing to create empty bundle.
> > This confuses me slightly because I thought a commit hash should also be a valid head _pointer_. 'git rev-list' also seems to agree with me on this.
> 
> A bundle is essentially a pack file with a header indicating the
> references contained within the bundle. If no reference is provided, the
> bundle is considered empty and git refuses to create it. I think this
> makes sense in the context of unbundling as you probably would not want
> to add new objects without updating references in the target repository.
> 
> From the git-bundle(1) docs for "create", the usage does say it accepts
> <git-rev-list-args> which may be a bit misleading because
> git-rev-list(1) does consider the commit hash as valid. Maybe that
> should be updated to indicate that proper references are expected.

That's somewhat weird indeed. I don't see a strong reason why the first
of the following commands works while the second one doesn't:

    $ git bundle create inc.bundle master~..master
    $ git bundle create inc.bundle $(git rev-parse master~)..$(git rev-parse master)

It's not like the bundle has "master" in its header in the first command
anyway, it only lists HEAD in there. So I'd claim that we could do the
same for the second command, as well.

Patrick