BlackGit is composed by client and server sides(the client and server are decoupled), two pieces make it useful for large, permission-sensitive repos:

- Cli Partial clone + sparse, per-user views on the client (git black, Python) — wraps stock git: Initially clone withblob:none, sparse-checkout set !/* !// checkout nothing then materialize only the files the user explicitlyfollows. No LFS, no full history of a multi-GB repo.

- Cli Agent A mini agent to use natural languages to control blackgit and git

- Server path-level blob authorization BlackGit Server sits in front of a standard Git server (GitLab/GitHub) as a smart-HTTP cache and access-control layer, refuses to hand out blobs that fall outside the caller's authorized paths.

BlackGit Cli (Python) could be used spearately to handle Github/GitLab repositories.

BlackGit Server is a standard git smart-HTTP endpoint (Netty + JGit) that proxies a real upstream origin.

git-black (blackgitcli.py) blackgit server (Netty + JGit)

ordinary git + smart-http ──────────────────▶ authenticates (Authorization: Basic)

partial clone (blob:none) │

sparse-checkout "cared files" ├─ read : blob allowlist by path (SVN authz format)

│ on-demand single-sha backfill from origin

│ download only needed sha

└─ write: canPush check + file-lock enforcement

proxy receive-pack to origin

replay the same body into the local cache

│

▼

origin (GitLab / GitHub)

client's token forwarded verbatim

The client and server are decoupled: client works against any git smart-HTTP remote (a bare GitLab, GitHub, or BlackGit itself).

- AuthN: every smart-HTTP request must carry Authorization: Basic <user:token>. The server decodes only the username for its own decisions; the raw header is forwarded to origin verbatim so upstream authenticates as the same user.

- AuthZ (read): each repo may carry a blackw-authzfile in standard SVNauthzformat (groups,@group,*,r/w). The user's granted path prefixes become a blob allowlist: commits and trees are always served (history and directory navigation keep working), but a blob whose path is not covered by anrgrant is refused on the wire. With noblackw-authzfile, every blob is downloadable (open mode).

- AuthZ (write): push requires a wgrant somewhere inblackw-authz. Force-push and ref deletion are rejected by JGit.--read-onlyrejects all pushes server-wide.

- The allowlist is computed over reachable history (not just the tip) and cached; it is invalidated after each push.

- File locks: git black lock <file>records who locked a file server-side. Subsequent pushes touching that file are rejected unless they come from the locker.git black lock -d <file>unlocks. A second lock on an already-locked file returns the current locker.

blackgitcli.py is a thin wrapper around stock git — it talks ordinary smart-HTTP and never requires the BlackGit server.

Auth is left to git's standard HTTP layer (credential helper / keychain / http.extraHeader); black never parses user info out of the URL. Your cared-file set lives in .git/blackw-add.tsv and is purely a client-side view (what lands in your worktree). It is independent of the server-side blob allowlist, which is the actual security boundary.

pip install blackgitThen:

git black clone https://gitlab.example.com/group/repo.git

cd repo

git black follow src/engine # start caring about a subtree

git black update # commits only; trees/blobs on demandPre-built images are on GitHub Container Registry:

docker pull ghcr.io/zhuzhonghua/blackgit:latestRun with env vars (no config file needed):

docker run -d \

-p 8081:8081 \

-v /data/blackgit:/data \

-e BLACKGIT_PORT=8081 \

-e BLACKGIT_UPSTREAM=https://github.com/user/repo.git \

ghcr.io/zhuzhonghua/blackgit:latestEnvironment variables:

lein uberjar

java -jar target/blackgit-*-standalone.jar \

--port 8081 --root /path/to/repos \

[--upstream https://github.com/user/repo.git] \

[--tls --keystore … --keystore-password …] [--read-only]A URL like http://host:8081/repo.git resolves to <root>/repo. If --upstream is set, the server creates an empty bare repo on first start and lazily fetches refs from upstream on the first client request (same strategy as josh).

- Server: Java 21, JGit 6.10, Netty 4.1; built with Leiningen.

- Client: Python 3; plain git subprocesses. Git 2.54+ required for partial clone.

- Transport: git smart-HTTP over HTTP/1.1 (optionally TLS). Only standard HTTP(S) git is supported; non-HTTP connections are dropped on first bytes.