Skip to content

Make bundle-uri compatible with shallow clones

At the moment git-clone(1) is not able to use --bundle-uri in combination with shallow clones (using either --depth, --shallow-since, or --shallow-exclude).

The incompatibility was initially introduced in e21e663c submitted by https://lore.kernel.org/git/ed76d84c5a7def525ab39a8acecdac8bad12c54b.1660050704.git.gitgitgadget@gmail.com/.

I understand there are good reasons why this is not supported, many because it's arguable what the expected behavior should be.

Problem

When a user makes a shallow clone, they want to limit the number of objects they store in their clone of the repository. They can do this for several reasons:

  1. To reduce storage size: The whole repository might be very big to store on disk.
  2. To speed up the clone: For example in CI only a given version of the repo is needed, they don't need a copy of the full history. So to complete the CI job as fast as possible, a shallow clone is used.

When you use bundle-uri, the client will download and unpack a bundle of objects before it starts negotiating objects with the server. During this first step, it might put objects in the object database, that otherwise the shallow clone would not have put there.

Notes

During testing I've seen the incompatibility only exists when the user passes --bundle-uri. When the server advertises bundles, and the client has transfer.bundleURI set, the client downloads the bundle, and the shallow clone will be less shallow:

$ git clone --depth=1 --bare http://127.0.0.1:8080/git/git.git nobundle-git.git
Cloning into bare repository 'nobundle-git.git'...
remote: Enumerating objects: 4492, done.
remote: Counting objects: 100% (4492/4492), done.
remote: Compressing objects: 100% (3936/3936), done.
remote: Total 4492 (delta 473), reused 2381 (delta 385), pack-reused 0
Receiving objects: 100% (4492/4492), 10.92 MiB | 38.03 MiB/s, done.
Resolving deltas: 100% (473/473), done.

$ git -c transfer.bundleURI=true clone --depth=1 --bare http://127.0.0.1:8080/git/git.git bundle-git.git
Cloning into bare repository 'bundle-git.git'...
remote: Enumerating objects: 1119, done.
remote: Counting objects: 100% (1119/1119), done.
remote: Compressing objects: 100% (490/490), done.
remote: Total 570 (delta 540), reused 98 (delta 79), pack-reused 0
Receiving objects: 100% (570/570), 206.12 KiB | 41.22 MiB/s, done.
Resolving deltas: 100% (540/540), completed with 540 local objects.

# check the size of the clones
$ du -sh *.git
115M	bundle-git.git
12M	nobundle-git.git

# the bundle that is advertised by the server
$ du -h bundle/git.bundle
101M	bundle/git.bundle
Edited by Toon Claes