I'm pleased to announce that I have Git fully passing the testsuite and CI in interoperability mode, both with SHA-256 and SHA-1 as the main algorithm. While this is very exciting, the work is not ready to send to the list and is effectively a draft, since there is still cleanup and efficiency work to be done.
What is fully functional:
* The testsuite. * The protocol, including extensions for mapping objects to support shallow clones, submodules, and partial clones and interoperability with remotes of different algorithms. * A full complement of functionality for everyday use cases.
Features which are currently unsupported (and which may or may not be supported in the future):
* Filtered bundles are unsupported because there is currently no way to provide a mapping. * Multi-pack index cannot be used as the sole pack index format because it does not yet provide mappings. * Pack index v1 and v2 cannot be used because they do not provide object mappings. Git automatically uses pack index v3 instead when necessary, which does handle mappings. * Packfile URIs are not supported because the protocol-provided packfile is not complete and its objects cannot be mapped. * Large object promisors cannot be used if the server does not actually have the entire history, since the server must have a complete history in order to provide object mappings. * `git fast-import` does not accept submodules in compatibility mode because there is no provision for mappings. * Remote helpers do not emit signatures in the compatibility algorithm for signed tags. * The WebDAV-based HTTP protocol doesn't support interoperability due to the lack of a way to distribute mappings.
Some additional things that may need to be improved:
* We have some recursive delta resolution code in `git index-pack` that
will need to be made iterative to avoid stack overflows.
* We need to batch object maps whenever we write them, since having too
many causes `git gc` to kick off frequently (which can be seen in some
tests). This will require substantial refactoring of code like `git
add`, since any time we write an object we must be sure to always
write the mapping (even if we `die`).
* We will probably want to move the object map repacking code out of
`git gc` into a separate command that we can call manually.
* We may want some debugging tools for pack index v3 and other data
formats so that we can show the mapping of objects.
* We will probably want to be able to sign in only one algorithm instead
of always in both. Users may not want to sign the SHA-1 format for
security reasons.
* There is some extremely basic code for `^{sha1}` and `^{sha256}` to
help `git rev-list` perform connectivity checks for remotes using the
compatibility algorithm, but it is very much incomplete and will need
to be completed or fenced off.
* Operations can be rather slow in some cases and we'll want to see what
speedups we can perform.
* Probably other things I have forgotten.There is new documentation in `Documentation/gitformat-hash.adoc` that outlines the requirements for using the protocol. The protocol restrictions described there are hard technical limitations that cannot be avoided; I've intentionally made things as featureful as they can be. This imposes real restrictions on using protocol interoperability with many projects, including Git and Linux[0]. Interested parties may wish to look at t1017 to see what's tested vis-à-vis the protocol and interoperability.
On the end of the series is a small amount of new Rust code that moves us in the direction of object file conversion in Rust. All the pointer arithmetic makes me very nervous from a security perspective, especially in network-facing code, so my hope is to eventually port that code over. Note that Rust is already required for the interoperability work, so this doesn't add any new dependencies.
I also have some unpublished code that could start on in-place migration functionality much like is done with `git refs migrate` once the Rust prerequisites above are ready. This could also make it possible at some point to migrate any relevant submodules as part of the migration of the main repository. I may or may not complete this work, but perhaps someone else will want to pick it up if I do not. I'm certain that such code would be valuable to many people, including forges.
I intend to rebase and tidy this work for at least a little while, but don't actually intend to send it upstream, since there are some technical limitations that prevent me from doing so. I have, however, been in contact with someone (who may identify themselves if they choose) who is interested in getting some of the polishing and upstreaming work done, which I deeply appreciate.
If you're interested in testing or perusing the work, you may get it from the `sha256-interop` branch of https://github.com/bk2204/git.git. Please note that it may be rebased, rewound, or otherwise folded, spindled, or mutilated at any time.
Even though the testsuite is passing earlier than I expected, I don't expect it to make Git 3.0, nor do I think we should delay Git 3.0 for this work. There are approximately 200 patches currently (and more to come if we add in-place migration tooling), so it seems very unlikely that we could get the entire series upstream in any reasonable amount of time. We will also very much want to give this time in an experimental state so people can try it out and report back on things that should be improved, which is further evidence that it's not right for Git 3.0.
I'm happy to answer any further questions if folks have any.
[0] Git uses submodules, which would need to be rewritten first in order to migrate, and Linux uses mergetags for which the tagged object is not in the history (which makes mapping the commit containing it fail).
-- brian m. carlson (they/them) Toronto, Ontario, CA