bazelbuild / bazelbuild/bazel

Allow having a git store in the local cache, to accelerate git dependencies

Open
#30,183 0 comments 0 reactions 0 assignees View on GitHub
P2 team-ExternalDeps type: feature request
Dominant language
Java
Stars
25.8k
Forks
4.6k
Avg merge
2d 20h
Merged PRs (30d)
72

Description

### Description of the feature request:

(Note: I discussed this idea [here](https://bazelbuild.slack.com/archives/CA31HN1T3/p1783415150638519). I post it here since I would still like to get more feedback.)

Currently, when I use `git_override` for `bazel_dep`, if the commit isn't already in the cache, Bazel does a full shallow clone of the repository. This is wasted work if the actual tree is similar to an already-cached tree. My idea is that instead, the Bazel cache would contain a `.git` object store, and `git_override` will just do a git fetch of the commit into it, without updating any git working directory. Then, the Bazel VFS would be used to retrieve blobs from the git store instead of from an actual drive.

### Which category does this issue belong to?

Performance

### What underlying problem are you trying to solve with this feature?

In my company we have a large monorepo, that is used to create many different targets. Many executables need to be tested on specific machines. In order to test a commit in CI, we need to decide what to build (which can be a lot, much more than what is actually needed), have the scripts put everything in a network drive ( which takes a long time), and then run what's needed on the remote machine from the network drive. Instead, I think of using Bazel on the remote machine to run the test: It would find what's needed in order to run the executable, build it if needed (but it will usually be already cached), retrieve the needed files from the Bazel cache, and run what's needed.

This currently requires checking out the entire monorepo on the remote machine. I can probably optimize this by having the CI script reuse a git working directory, thus updating only the changed files from the previous run, and also have a post-checkout script update sha256 xattrs of modified files. But this still is not free, and if the previous commits differs a lot from the current one, it means updating a lot of files.

Instead, my idea is for the CI script to create a directory with just a few files, one of them is a MODULE.bazel file which refers to the commit that needs testing. (I would probably also need to extract the MODULE.lock file from the actual commit I want to test). Currently Bazel downloads and extracts the entire monorepo tree for this. But if the feature is implemented, it would only need to fetch the new git objects into the cache, which would be much faster. If the Bazel hash method is configured to be GITSHA1 then the caches would be immediately available from the git store. If not, then a mapping from gitsha1 hashes to the Bazel hash could be also kept in the cache, so that the sha256 hash would only be computed once per blob.

Another way to think about my use case is this. Currently we have a lot of executables that depend on each other, sometimes using docker images and globally installed files. I'm thinking of Nix as an inspiration, where dependencies between executables are explicit, and at the end all come from a monorepo (nixpkgs), where I can update a source file and have the entire execution use the new version. I think of using Bazel in a similar way, where in order to execute something I just need the monorepo commit hash and a target name, and then use Bazel to build or retrieve from the cache what's needed, and run the executable.

An alternative method, that came up in the discussion, is to use `bazel test`, by installing a runner on the target machine and managing exec properties so the scheduler would choose the right machine. This is certainly possible, and can be a great way to run some tests, but it requires an architectural change that is not always suitable.

Another possible alternative is to use FUSE to create a virtual filesystem that exposes a git commit. However, I didn't find any performant, relatively well maintained and supported, FUSE filesystem. Another issue with this approach is that it requires OS support and special OS privileges.

The bottom line: I think this makes an interesting use case significantly more performant, and doesn't change the user-facing interface at all. So this might mean it could be a good idea.

### Which operating system are you running Bazel on?

linux

### Have you found anything relevant by searching the web?

I have found issues related to issues with `git_override` which are related to different versions of the installed `git` executable. This change would mean that Bazel would directly interface with git stores (for example by bundling gitoxide and using jni-rs), so it may also help with those issues.

### Any other information, logs, or outputs that you want to share?

I hope I'll be able to implement this. I want to gather more feedback before I try.

Thanks!
Noam

Contributor guide

Open the contributing guide

Research direction

Start by tracing the git_override entry point and the MODULE.bazel/MODULE.lock setup described in the issue. Compare the current shallow-clone behavior with the proposed cached Git object store and VFS access; done means a commit can be fetched into the cache without updating a working tree while preserving dependency resolution and cache behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
git
Domain
build-system, performance
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.