Volume XXII, number 279Tuesday, October 6, 2026Latest message 19 minutes ago

The Git List

News and archive of git@vger.kernel.org, since April 2005

a "limbo" object-format state for empty repositories?

6 messages between Oct 2, 2026 and Oct 5, 2026, from Jeff King, brian m. carlson, Junio C Hamano.

Plain Markdown or JSON for tools and agents.

Jeff KingOct 2, 2026, 22:44 UTC on lore

Reading Scott's blog post and accompanying HN comments the other day, one upcoming usability headache stood out to me: first-time pushes to newly created repositories.

If you create a bare repo on a forge like GitHub, it must be either sha1 or sha256. If the forge continues to create sha1 bare repos by default, then all of the post-3.0 sha256 users will get this on first push:

  $ git push
  fatal: the receiving end does not support this repository's hash algorithm
  fatal: the remote end hung up unexpectedly

And then they have to go switch or recreate their remote repo. And if the forge flips to sha256, then we have the opposite problem for pre-3.0 users (and even 3.0 users who are doing a first-push of existing sha1 repositories).

Savvy users will of course specify the object format they expect to use when they create the server-side repo. But most users won't know or care about this, and even if they do, it's an easy thing to forget about. So I expect we'll see a lot of frustration here.

It would be nice if the empty repository could adapt to the object format used by its first push. Then everything would just work from the user's perspective, no matter what they push.

GitHub has long done something similar for the HEAD pointer; on first push of a single branch it is pointed at that branch. There it was not too hard to add custom code around Git that detected the situation and set up the symref. But I don't think you can quite do the same thing for the object format, because the push advertisement actually says "hey, I'm a <hash> repo" in its capabilities. So the client says "oh, that doesn't match me" and bails before actually pushing anything.

So what I'm suggesting instead is that the server be allowed to advertise a limbo state: it has no object format yet. And then client can recognize object-format=limbo, and send back "I'm a <sha1|sha256> repo, so that's what I'm sending you" in its capabilities response. And then the server receives that and shifts its local object-format to match.

There are some tricky bits on the server side (e.g., you'd want to flip the value atomically so that if you get two simultaneous mismatched pushes, one of them gets rejected). But I can't think of any reason that it couldn't conceptually work, and I feel like it would save a lot of headaches.

But I also did just think of this idea, and haven't implemented anything (nor do I have immediate plans to). So it might be half-baked. But I thought I'd toss it out there and see if any body has thoughts, or feels strongly enough to try implementing it.

-Peff
brian m. carlsonOct 3, 2026, 01:07 UTC in reply to Jeff King on lore

Re: a "limbo" object-format state for empty repositories?

On 2026-10-02 at 22:44:00, Jeff King wrote:
> It would be nice if the empty repository could adapt to the object
> format used by its first push. Then everything would just work from the
> user's perspective, no matter what they push.
I agree that would be nice.
Show 17 quoted lines
> So what I'm suggesting instead is that the server be allowed to
> advertise a limbo state: it has no object format yet. And then client
> can recognize object-format=limbo, and send back "I'm a <sha1|sha256>
> repo, so that's what I'm sending you" in its capabilities response.  And
> then the server receives that and shifts its local object-format to
> match.
> 
> There are some tricky bits on the server side (e.g., you'd want to flip
> the value atomically so that if you get two simultaneous mismatched
> pushes, one of them gets rejected). But I can't think of any reason that
> it couldn't conceptually work, and I feel like it would save a lot of
> headaches.
> 
> But I also did just think of this idea, and haven't implemented anything
> (nor do I have immediate plans to). So it might be half-baked. But I
> thought I'd toss it out there and see if any body has thoughts, or feels
> strongly enough to try implementing it.

That is definitely something that could be added, but it's also incompatible with every existing implementation. Specifically using the `object-format=limbo` approach means that no existing client from 2.29 on will work with the repository since `limbo` is not a valid hash algorithm.

There is some support for multiple `object-format` directives, but I don't know how well it works and I seem to remember that we had some sort of crasher bug in the past. That would be the best possible way to advertise that, though, if older versions support it.

There are also going to be some policy decisions, for instance. Some organizations will not want to allow one algorithm or the other, so Git will need some way to allow that behaviour to be expressed. Or more likely, Git needs some way to allow the fact that it's in versatile mode to be expressed and that it's safe to rewrite the config on initial write into the repository (which, to be clear, need not be a push; it could also be a commit or add).

All that being said, it's not impossible, but it's also not easy.
-- 
brian m. carlson (they/them)
Toronto, Ontario, CA
Jeff KingOct 3, 2026, 01:25 UTC in reply to brian m. carlson on lore

Re: a "limbo" object-format state for empty repositories?

On Sat, Oct 03, 2026 at 01:07:48AM +0000, brian m. carlson wrote:
Show 10 quoted lines
> > But I also did just think of this idea, and haven't implemented anything
> > (nor do I have immediate plans to). So it might be half-baked. But I
> > thought I'd toss it out there and see if any body has thoughts, or feels
> > strongly enough to try implementing it.
> 
> That is definitely something that could be added, but it's also
> incompatible with every existing implementation.  Specifically using the
> `object-format=limbo` approach means that no existing client from 2.29
> on will work with the repository since `limbo` is not a valid hash
> algorithm.

Yeah, that is a problem. It breaks older clients (that are at least new enough to understand object-format=) worse than a mismatched format does. I was thinking we could solve that with a new capability, let's call it "magic-limbo" for a moment. Older versions would ignore it.

But then what do we put in the object-format= field? We have to put _something_ valid, as even if we put nothing that is an implicit choice of sha1.

So I think the best we can do is advertise magic-limbo, and then new limbo-aware clients can always do the right thing. Clients which are new enough to understand object-format but don't understand limbo will use the server's object-format unconditionally. So the choice there does still matter. But if we don't switch to sha256-by-default until magic-limbo is implemented, then anybody who has a local sha256 repo got there intentionally, and presumably knows enough to configure the server side to match. So the sensible protocol advertisement for a limbo repo is "magic-limbo" plus "object-format=sha1".

> There is some support for multiple `object-format` directives, but I
> don't know how well it works and I seem to remember that we had some
> sort of crasher bug in the past.  That would be the best possible way to
> advertise that, though, if older versions support it.

Yeah, I thought about emitting multiple but it seems like that introduces other weird corner cases. I think we really need a new capability so that new versions and use it and old ones will ignore it.

Show 7 quoted lines
> There are also going to be some policy decisions, for instance.  Some
> organizations will not want to allow one algorithm or the other, so
> Git will need some way to allow that behaviour to be expressed.  Or more
> likely, Git needs some way to allow the fact that it's in versatile
> mode to be expressed and that it's safe to rewrite the config on initial
> write into the repository (which, to be clear, need not be a push; it
> could also be a commit or add).

Those parts seem outside of the scope of Git, or at least its protocol. But yeah, I'd expect a forge like GitHub to let you say "do not allow the creation of sha1 repos in this account/org", and the object-format selector for a new repo (at the forge UI) should be a tri-state: sha1, sha256, or limbo. How that translates into Git commands is TBD: whether via config, or more likely, that you have to select the limbo state explicitly with a command-line option to git-init.

-Peff
Junio C HamanoOct 3, 2026, 01:31 UTC in reply to brian m. carlson on lore

Re: a "limbo" object-format state for empty repositories?

"brian m. carlson" <sandals@crustytoothpaste.net> writes:
> There is some support for multiple `object-format` directives, but I
> don't know how well it works and I seem to remember that we had some
> sort of crasher bug in the past.  That would be the best possible way to
> advertise that, though, if older versions support it.

Oh, bad. Telling the other sides "I can accept this and that hash algorithm" with multiple capability advertisement is so obviously the right thing to do at the conceptual level. It would have been very nice if it worked.

brian m. carlsonOct 3, 2026, 14:22 UTC in reply to Jeff King on lore

Re: a "limbo" object-format state for empty repositories?

On 2026-10-03 at 01:25:12, Jeff King wrote:
Show 18 quoted lines
> Yeah, that is a problem. It breaks older clients (that are at least new
> enough to understand object-format=) worse than a mismatched format
> does. I was thinking we could solve that with a new capability, let's
> call it "magic-limbo" for a moment. Older versions would ignore it.
> 
> But then what do we put in the object-format= field? We have to put
> _something_ valid, as even if we put nothing that is an implicit choice
> of sha1.
> 
> So I think the best we can do is advertise magic-limbo, and then new
> limbo-aware clients can always do the right thing. Clients which are new
> enough to understand object-format but don't understand limbo will use
> the server's object-format unconditionally. So the choice there does
> still matter. But if we don't switch to sha256-by-default until
> magic-limbo is implemented, then anybody who has a local sha256 repo got
> there intentionally, and presumably knows enough to configure the server
> side to match. So the sensible protocol advertisement for a limbo repo
> is "magic-limbo" plus "object-format=sha1".

We need to declare the other object format as well because we need to know that the server specifically supports SHA-256. If we add a third hash algorithm, then maybe SHA-256 is unacceptable for that reason. So maybe `alt-object-format=sha256`. We do definitely need to be sure that multiple options are accepted, though.

As I say below, we probably need to initialize with some hash algorithm at first, so we could also have `object-format=sha256` and `alt-object-format=sha1`.

You hint at delaying SHA-256-by-default until this is implemented, but I don't think that's a good idea. I agree this would be a nice feature to implement, but I have no intention of implementing it and you said you didn't, either, so unless someone decides that they are going to implement it imminently, I don't think we should hold up Git 3.0 or the default algorithm change to then. As I mentioned, Git is really behind the times on moving away from SHA-1 and we need our users to choose sensible defaults as soon as possible. Git 3.0 moving to SHA-256 by default was announced in 2024 and given that I managed to write a functional interoperability implementation in that time, there has been plenty of time to say something and implement a solution.

> Yeah, I thought about emitting multiple but it seems like that
> introduces other weird corner cases. I think we really need a new
> capability so that new versions and use it and old ones will ignore it.

The bug I mentioned was apparently not a crasher but an infinite loop: aa962fef27 ("v0 protocol: fix infinite loop when parsing multi-valued capabilities", 2023-04-14). However, it was fixed in 2.41, before SHA-256 became stable in 2.44. We could therefore implement it that way if we're willing to abandon versions of Git that only have experimental support for SHA-256.

Show 7 quoted lines
> Those parts seem outside of the scope of Git, or at least its protocol.
> But yeah, I'd expect a forge like GitHub to let you say "do not allow
> the creation of sha1 repos in this account/org", and the object-format
> selector for a new repo (at the forge UI) should be a tri-state: sha1,
> sha256, or limbo. How that translates into Git commands is TBD: whether
> via config, or more likely, that you have to select the limbo state
> explicitly with a command-line option to git-init.

I disagree that they're outside the scope of Git, but I do agree that we should add support for this either in the config or via a command-line option. I think config would be better here because we also have to deal with the fact that someone might use commands other than push to write into the repository (on a forge, that might be the API) and we need to specify _some_ hash algorithm for that case.

-- 
brian m. carlson (they/them)
Toronto, Ontario, CA
Jeff KingOct 5, 2026, 03:30 UTC in reply to brian m. carlson on lore

Re: a "limbo" object-format state for empty repositories?

On Sat, Oct 03, 2026 at 02:22:32PM +0000, brian m. carlson wrote:
Show 15 quoted lines
> > So I think the best we can do is advertise magic-limbo, and then new
> > limbo-aware clients can always do the right thing. Clients which are new
> > enough to understand object-format but don't understand limbo will use
> > the server's object-format unconditionally. So the choice there does
> > still matter. But if we don't switch to sha256-by-default until
> > magic-limbo is implemented, then anybody who has a local sha256 repo got
> > there intentionally, and presumably knows enough to configure the server
> > side to match. So the sensible protocol advertisement for a limbo repo
> > is "magic-limbo" plus "object-format=sha1".
> 
> We need to declare the other object format as well because we need to
> know that the server specifically supports SHA-256.  If we add a third
> hash algorithm, then maybe SHA-256 is unacceptable for that reason.  So
> maybe `alt-object-format=sha256`.  We do definitely need to be sure that
> multiple options are accepted, though.

Right, that makes sense. And the presence of alt-object-format would replace the need for a separate magic-limbo at all.

> As I say below, we probably need to initialize with some hash algorithm
> at first, so we could also have `object-format=sha256` and
> `alt-object-format=sha1`.
Yeah, that makes sense.
> You hint at delaying SHA-256-by-default until this is implemented, but I
> don't think that's a good idea.

I wasn't proposing a delay. There's at least another whole release cycle before 3.0, and this feature doesn't seem all that big. So it seemed like something that could be implemented in that time-frame. I may or may not work on it at some point; I just don't want to preclude anybody (like Scott) who is interested and wanted to run with it.

Show 14 quoted lines
> > Those parts seem outside of the scope of Git, or at least its protocol.
> > But yeah, I'd expect a forge like GitHub to let you say "do not allow
> > the creation of sha1 repos in this account/org", and the object-format
> > selector for a new repo (at the forge UI) should be a tri-state: sha1,
> > sha256, or limbo. How that translates into Git commands is TBD: whether
> > via config, or more likely, that you have to select the limbo state
> > explicitly with a command-line option to git-init.
> 
> I disagree that they're outside the scope of Git, but I do agree that we
> should add support for this either in the config or via a command-line
> option.  I think config would be better here because we also have to
> deal with the fact that someone might use commands other than push to
> write into the repository (on a forge, that might be the API) and we
> need to specify _some_ hash algorithm for that case.

Sorry, I just meant that policy decisions like "this account should not be able to create sha1 repos" was outside of Git. We definitely need some config flag to mark the limbo state (since it's set by "git init" and ultimately respected by receive-pack and elsewhere). I would say that any limbo-state feature should _not_ be on by default, but could be a useful building block for forges that want to reduce friction. There'd perhaps be some forge-specific work to do on top, too.

-Peff

Back to recent threads