{"thread":{"id":"66452","subject":"a \"limbo\" object-format state for empty repositories?","startedAt":"2026-10-02T22:44:02Z","lastAt":"2026-10-05T03:30:24Z","messageCount":6,"participants":["Jeff King","brian m. carlson","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"554020","messageId":"20261002224400.GA834158@coredump.intra.peff.net","threadId":"66452","inReplyTo":null,"subject":"a \"limbo\" object-format state for empty repositories?","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2026-10-02T22:44:00Z","receivedAt":"2026-10-02T22:44:02Z","isPatch":false,"body":"Reading Scott's blog post and accompanying HN comments the other day,\none upcoming usability headache stood out to me: first-time pushes to\nnewly created repositories.\n\nIf you create a bare repo on a forge like GitHub, it must be either sha1\nor sha256. If the forge continues to create sha1 bare repos by default,\nthen all of the post-3.0 sha256 users will get this on first push:\n\n  $ git push\n  fatal: the receiving end does not support this repository's hash algorithm\n  fatal: the remote end hung up unexpectedly\n\nAnd then they have to go switch or recreate their remote repo. And if\nthe forge flips to sha256, then we have the opposite problem for pre-3.0\nusers (and even 3.0 users who are doing a first-push of existing sha1\nrepositories).\n\nSavvy users will of course specify the object format they expect to use\nwhen they create the server-side repo. But most users won't know or care\nabout this, and even if they do, it's an easy thing to forget about. So\nI expect we'll see a lot of frustration here.\n\nIt would be nice if the empty repository could adapt to the object\nformat used by its first push. Then everything would just work from the\nuser's perspective, no matter what they push.\n\nGitHub has long done something similar for the HEAD pointer; on first\npush of a single branch it is pointed at that branch. There it was not\ntoo hard to add custom code around Git that detected the situation and\nset up the symref. But I don't think you can quite do the same thing for\nthe object format, because the push advertisement actually says \"hey,\nI'm a <hash> repo\" in its capabilities. So the client says \"oh, that\ndoesn't match me\" and bails before actually pushing anything.\n\nSo what I'm suggesting instead is that the server be allowed to\nadvertise a limbo state: it has no object format yet. And then client\ncan recognize object-format=limbo, and send back \"I'm a <sha1|sha256>\nrepo, so that's what I'm sending you\" in its capabilities response.  And\nthen the server receives that and shifts its local object-format to\nmatch.\n\nThere are some tricky bits on the server side (e.g., you'd want to flip\nthe value atomically so that if you get two simultaneous mismatched\npushes, one of them gets rejected). But I can't think of any reason that\nit couldn't conceptually work, and I feel like it would save a lot of\nheadaches.\n\nBut I also did just think of this idea, and haven't implemented anything\n(nor do I have immediate plans to). So it might be half-baked. But I\nthought I'd toss it out there and see if any body has thoughts, or feels\nstrongly enough to try implementing it.\n\n-Peff\n"},{"id":"554035","messageId":"asBVY1WniGUo6bQS@fruit.crustytoothpaste.net","threadId":"66452","inReplyTo":"20261002224400.GA834158@coredump.intra.peff.net","subject":"Re: a \"limbo\" object-format state for empty repositories?","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2026-10-03T01:07:48Z","receivedAt":"2026-10-03T01:07:50Z","isPatch":false,"body":"On 2026-10-02 at 22:44:00, Jeff King wrote:\n> It would be nice if the empty repository could adapt to the object\n> format used by its first push. Then everything would just work from the\n> user's perspective, no matter what they push.\n\nI agree that would be nice.\n\n> So what I'm suggesting instead is that the server be allowed to\n> advertise a limbo state: it has no object format yet. And then client\n> can recognize object-format=limbo, and send back \"I'm a <sha1|sha256>\n> repo, so that's what I'm sending you\" in its capabilities response.  And\n> then the server receives that and shifts its local object-format to\n> match.\n> \n> There are some tricky bits on the server side (e.g., you'd want to flip\n> the value atomically so that if you get two simultaneous mismatched\n> pushes, one of them gets rejected). But I can't think of any reason that\n> it couldn't conceptually work, and I feel like it would save a lot of\n> headaches.\n> \n> But I also did just think of this idea, and haven't implemented anything\n> (nor do I have immediate plans to). So it might be half-baked. But I\n> thought I'd toss it out there and see if any body has thoughts, or feels\n> strongly enough to try implementing it.\n\nThat is definitely something that could be added, but it's also\nincompatible with every existing implementation.  Specifically using the\n`object-format=limbo` approach means that no existing client from 2.29\non will work with the repository since `limbo` is not a valid hash\nalgorithm.\n\nThere is some support for multiple `object-format` directives, but I\ndon't know how well it works and I seem to remember that we had some\nsort of crasher bug in the past.  That would be the best possible way to\nadvertise that, though, if older versions support it.\n\nThere are also going to be some policy decisions, for instance.  Some\norganizations will not want to allow one algorithm or the other, so\nGit will need some way to allow that behaviour to be expressed.  Or more\nlikely, Git needs some way to allow the fact that it's in versatile\nmode to be expressed and that it's safe to rewrite the config on initial\nwrite into the repository (which, to be clear, need not be a push; it\ncould also be a commit or add).\n\nAll that being said, it's not impossible, but it's also not easy.\n-- \nbrian m. carlson (they/them)\nToronto, Ontario, CA\n"},{"id":"554037","messageId":"20261003012512.GA1324483@coredump.intra.peff.net","threadId":"66452","inReplyTo":"asBVY1WniGUo6bQS@fruit.crustytoothpaste.net","subject":"Re: a \"limbo\" object-format state for empty repositories?","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2026-10-03T01:25:12Z","receivedAt":"2026-10-03T01:25:15Z","isPatch":false,"body":"On Sat, Oct 03, 2026 at 01:07:48AM +0000, brian m. carlson wrote:\n\n> > But I also did just think of this idea, and haven't implemented anything\n> > (nor do I have immediate plans to). So it might be half-baked. But I\n> > thought I'd toss it out there and see if any body has thoughts, or feels\n> > strongly enough to try implementing it.\n> \n> That is definitely something that could be added, but it's also\n> incompatible with every existing implementation.  Specifically using the\n> `object-format=limbo` approach means that no existing client from 2.29\n> on will work with the repository since `limbo` is not a valid hash\n> algorithm.\n\nYeah, that is a problem. It breaks older clients (that are at least new\nenough to understand object-format=) worse than a mismatched format\ndoes. I was thinking we could solve that with a new capability, let's\ncall it \"magic-limbo\" for a moment. Older versions would ignore it.\n\nBut then what do we put in the object-format= field? We have to put\n_something_ valid, as even if we put nothing that is an implicit choice\nof sha1.\n\nSo I think the best we can do is advertise magic-limbo, and then new\nlimbo-aware clients can always do the right thing. Clients which are new\nenough to understand object-format but don't understand limbo will use\nthe server's object-format unconditionally. So the choice there does\nstill matter. But if we don't switch to sha256-by-default until\nmagic-limbo is implemented, then anybody who has a local sha256 repo got\nthere intentionally, and presumably knows enough to configure the server\nside to match. So the sensible protocol advertisement for a limbo repo\nis \"magic-limbo\" plus \"object-format=sha1\".\n\n> There is some support for multiple `object-format` directives, but I\n> don't know how well it works and I seem to remember that we had some\n> sort of crasher bug in the past.  That would be the best possible way to\n> advertise that, though, if older versions support it.\n\nYeah, I thought about emitting multiple but it seems like that\nintroduces other weird corner cases. I think we really need a new\ncapability so that new versions and use it and old ones will ignore it.\n\n> There are also going to be some policy decisions, for instance.  Some\n> organizations will not want to allow one algorithm or the other, so\n> Git will need some way to allow that behaviour to be expressed.  Or more\n> likely, Git needs some way to allow the fact that it's in versatile\n> mode to be expressed and that it's safe to rewrite the config on initial\n> write into the repository (which, to be clear, need not be a push; it\n> could also be a commit or add).\n\nThose parts seem outside of the scope of Git, or at least its protocol.\nBut yeah, I'd expect a forge like GitHub to let you say \"do not allow\nthe creation of sha1 repos in this account/org\", and the object-format\nselector for a new repo (at the forge UI) should be a tri-state: sha1,\nsha256, or limbo. How that translates into Git commands is TBD: whether\nvia config, or more likely, that you have to select the limbo state\nexplicitly with a command-line option to git-init.\n\n-Peff\n"},{"id":"554038","messageId":"xmqq33unvabf.fsf@gitster.g","threadId":"66452","inReplyTo":"asBVY1WniGUo6bQS@fruit.crustytoothpaste.net","subject":"Re: a \"limbo\" object-format state for empty repositories?","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-10-03T01:31:48Z","receivedAt":"2026-10-03T01:31:51Z","isPatch":false,"body":"\"brian m. carlson\" <sandals@crustytoothpaste.net> writes:\n\n> There is some support for multiple `object-format` directives, but I\n> don't know how well it works and I seem to remember that we had some\n> sort of crasher bug in the past.  That would be the best possible way to\n> advertise that, though, if older versions support it.\n\nOh, bad.  Telling the other sides \"I can accept this and that hash\nalgorithm\" with multiple capability advertisement is so obviously\nthe right thing to do at the conceptual level.  It would have been\nvery nice if it worked.\n\n"},{"id":"554066","messageId":"asEPp6Bg3xDpA4e1@fruit.crustytoothpaste.net","threadId":"66452","inReplyTo":"20261003012512.GA1324483@coredump.intra.peff.net","subject":"Re: a \"limbo\" object-format state for empty repositories?","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2026-10-03T14:22:32Z","receivedAt":"2026-10-03T14:22:34Z","isPatch":false,"body":"On 2026-10-03 at 01:25:12, Jeff King wrote:\n> Yeah, that is a problem. It breaks older clients (that are at least new\n> enough to understand object-format=) worse than a mismatched format\n> does. I was thinking we could solve that with a new capability, let's\n> call it \"magic-limbo\" for a moment. Older versions would ignore it.\n> \n> But then what do we put in the object-format= field? We have to put\n> _something_ valid, as even if we put nothing that is an implicit choice\n> of sha1.\n> \n> So I think the best we can do is advertise magic-limbo, and then new\n> limbo-aware clients can always do the right thing. Clients which are new\n> enough to understand object-format but don't understand limbo will use\n> the server's object-format unconditionally. So the choice there does\n> still matter. But if we don't switch to sha256-by-default until\n> magic-limbo is implemented, then anybody who has a local sha256 repo got\n> there intentionally, and presumably knows enough to configure the server\n> side to match. So the sensible protocol advertisement for a limbo repo\n> is \"magic-limbo\" plus \"object-format=sha1\".\n\nWe need to declare the other object format as well because we need to\nknow that the server specifically supports SHA-256.  If we add a third\nhash algorithm, then maybe SHA-256 is unacceptable for that reason.  So\nmaybe `alt-object-format=sha256`.  We do definitely need to be sure that\nmultiple options are accepted, though.\n\nAs I say below, we probably need to initialize with some hash algorithm\nat first, so we could also have `object-format=sha256` and\n`alt-object-format=sha1`.\n\nYou hint at delaying SHA-256-by-default until this is implemented, but I\ndon't think that's a good idea.  I agree this would be a nice feature to\nimplement, but I have no intention of implementing it and you said you\ndidn't, either, so unless someone decides that they are going to\nimplement it imminently, I don't think we should hold up Git 3.0 or the\ndefault algorithm change to then.  As I mentioned, Git is really behind\nthe times on moving away from SHA-1 and we need our users to choose\nsensible defaults as soon as possible.  Git 3.0 moving to SHA-256 by\ndefault was announced in 2024 and given that I managed to write a\nfunctional interoperability implementation in that time, there has been\nplenty of time to say something and implement a solution.\n\n> Yeah, I thought about emitting multiple but it seems like that\n> introduces other weird corner cases. I think we really need a new\n> capability so that new versions and use it and old ones will ignore it.\n\nThe bug I mentioned was apparently not a crasher but an infinite loop:\naa962fef27 (\"v0 protocol: fix infinite loop when parsing multi-valued\ncapabilities\", 2023-04-14).  However, it was fixed in 2.41, before\nSHA-256 became stable in 2.44.  We could therefore implement it that way\nif we're willing to abandon versions of Git that only have experimental\nsupport for SHA-256.\n\n> Those parts seem outside of the scope of Git, or at least its protocol.\n> But yeah, I'd expect a forge like GitHub to let you say \"do not allow\n> the creation of sha1 repos in this account/org\", and the object-format\n> selector for a new repo (at the forge UI) should be a tri-state: sha1,\n> sha256, or limbo. How that translates into Git commands is TBD: whether\n> via config, or more likely, that you have to select the limbo state\n> explicitly with a command-line option to git-init.\n\nI disagree that they're outside the scope of Git, but I do agree that we\nshould add support for this either in the config or via a command-line\noption.  I think config would be better here because we also have to\ndeal with the fact that someone might use commands other than push to\nwrite into the repository (on a forge, that might be the API) and we\nneed to specify _some_ hash algorithm for that case.\n-- \nbrian m. carlson (they/them)\nToronto, Ontario, CA\n"},{"id":"554138","messageId":"20261005033023.GA10271@coredump.intra.peff.net","threadId":"66452","inReplyTo":"asEPp6Bg3xDpA4e1@fruit.crustytoothpaste.net","subject":"Re: a \"limbo\" object-format state for empty repositories?","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2026-10-05T03:30:23Z","receivedAt":"2026-10-05T03:30:24Z","isPatch":false,"body":"On Sat, Oct 03, 2026 at 02:22:32PM +0000, brian m. carlson wrote:\n\n> > So I think the best we can do is advertise magic-limbo, and then new\n> > limbo-aware clients can always do the right thing. Clients which are new\n> > enough to understand object-format but don't understand limbo will use\n> > the server's object-format unconditionally. So the choice there does\n> > still matter. But if we don't switch to sha256-by-default until\n> > magic-limbo is implemented, then anybody who has a local sha256 repo got\n> > there intentionally, and presumably knows enough to configure the server\n> > side to match. So the sensible protocol advertisement for a limbo repo\n> > is \"magic-limbo\" plus \"object-format=sha1\".\n> \n> We need to declare the other object format as well because we need to\n> know that the server specifically supports SHA-256.  If we add a third\n> hash algorithm, then maybe SHA-256 is unacceptable for that reason.  So\n> maybe `alt-object-format=sha256`.  We do definitely need to be sure that\n> multiple options are accepted, though.\n\nRight, that makes sense. And the presence of alt-object-format would\nreplace the need for a separate magic-limbo at all.\n\n> As I say below, we probably need to initialize with some hash algorithm\n> at first, so we could also have `object-format=sha256` and\n> `alt-object-format=sha1`.\n\nYeah, that makes sense.\n\n> You hint at delaying SHA-256-by-default until this is implemented, but I\n> don't think that's a good idea.\n\nI wasn't proposing a delay. There's at least another whole release cycle\nbefore 3.0, and this feature doesn't seem all that big. So it seemed\nlike something that could be implemented in that time-frame. I may or may\nnot work on it at some point; I just don't want to preclude anybody\n(like Scott) who is interested and wanted to run with it.\n\n> > Those parts seem outside of the scope of Git, or at least its protocol.\n> > But yeah, I'd expect a forge like GitHub to let you say \"do not allow\n> > the creation of sha1 repos in this account/org\", and the object-format\n> > selector for a new repo (at the forge UI) should be a tri-state: sha1,\n> > sha256, or limbo. How that translates into Git commands is TBD: whether\n> > via config, or more likely, that you have to select the limbo state\n> > explicitly with a command-line option to git-init.\n> \n> I disagree that they're outside the scope of Git, but I do agree that we\n> should add support for this either in the config or via a command-line\n> option.  I think config would be better here because we also have to\n> deal with the fact that someone might use commands other than push to\n> write into the repository (on a forge, that might be the API) and we\n> need to specify _some_ hash algorithm for that case.\n\nSorry, I just meant that policy decisions like \"this account should not\nbe able to create sha1 repos\" was outside of Git. We definitely need\nsome config flag to mark the limbo state (since it's set by \"git init\"\nand ultimately respected by receive-pack and elsewhere). I would say\nthat any limbo-state feature should _not_ be on by default, but could be\na useful building block for forges that want to reduce friction. There'd\nperhaps be some forge-specific work to do on top, too.\n\n-Peff\n"}]}