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

From: Junio C Hamano <[email-masked]>
Date: Fri, 06 Dec 2024 03:45:24 +0900

Justin Tobler <[email-masked]> writes:

> When trying to unbundle an incremental bundle into a repository that
> lacks the prerequisite objects, Git fails. These prerequisite objects
> are also listed in the bundle header. Maybe it would be nice if we were
> able to create a shallow repository from this bundle.

The prerequisite objects are required for two reasons when unpacking
a bundle.  One is to ensure that the resulting history is complete,
as the central idea of bundle was to "freeze the over-the-wire data
transferred during a fetch" but it predates "shallow clone", which
allows a clone to be lacking history beyond certain point in the
topology.  The other is that the pack data stream recorded in a
bundle is allowed to be a "thin pack", with objects represented as a
delta against other objects that do not exist in the same pack---the
recipient is expected to supply these delta base objects to ensure
that these deltified objects can be reconstituted, which is where
the "prerequisite" comes from.

In order to allow creating a shallow clone out of a bundle when
using revision exclusions (see "git bundle --help"), we'd update the
bundle format to allow us to create a bundle using "thick pack",
which we do not currently do.  And more importantly, the recipient
must be able to identify such a "thick pack", as the data currently
defined, a bundle with "prerequisite" by definition is "thin" and
cannot be used to create a shallow clone out of.  Which means we'd
need an updated bundle file format.

> I'm not quite sure I follow. According to gitformat-bundle(5), we should
> see "obj-id SP refname LF" in the header. Inspecting the header of a
> bundle created from `git bundle create inc.bundle master~..master` also
> shows "refs/heads/master" in the header.

Yes, if there is one thing I regret in the way the bundle header was
designed and wish I could fix is to that we lack "HEAD" unless we
force to include it, and "git clone" out of a bundle sometimes fails
because of it (you can "git fetch" out of the bundle, naming the
refs you find in the bundle header instaed).

> It looks like when creating a bundle in `bundle.c:create_bundle()`, if
> the call to `write_bundle_refs()` returns a reference count of 0, git
> dies with the error seen. When a commit hash is used for the
> rev-list-arg, it is not able to determine a reference from it.

Yes.  It is not fundamental, though.  There are occasions where "git
fetch" that does not transfer any object data is still useful (e.g.,
when they create a new branch that points at a commit that already
is included in the history of another branch, you only need to learn
what that new ref is pointing at, but you already have all the
object data).  As the central idea of "bundle" is to freeze the data
that goes over the wire for a fetch (to allow you sneaker-net
instead of "git fetch"), a bundle that says "you are expected to
have the history reachable from these commits, now you be aware of
the fact that this and that ref points at this and that objects"
should be possible.  Such a bundle would have the prerequisite
section and the ref advertisement section, but there is no need for
any pack data.