grit
llms.txt586 starsChanged 5 days agoMITView on GitHub
How to use grit, a simple Git client built on grit-lib. Start with the tutorial, then look up any command or open the library guide. Grit is two things: If you're new to the command line, start with the tutorial. If you're wiring Git into a Rust program, start with the library quick start and the library guide overview. Use grit when you want a day-to-day Git client from the terminal or in scripts (--json / --filter). Use grit-lib when…
- Pipes a download into a shell
- Installs packages
- Commits and pushes
In this repository4 other files it gives its agents.
- AGENTS.mdAGENTS.md
- site/AGENTS.mdAGENTS.md
- docs/llms.txtllms.txt
- butSkill
The file
Show its rules and text
We split this llms-full.txt into the rules it gives an agent
29 rules. About 0 are common, 15 are distinctive, and 14 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈15
Distinctive · estimate
This author's own choices. Worth a look.
14
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 21
If you're new to the command line, start with the tutorial.
- Very specific: line 38
Every page also has a Markdown twin: replace index.html with index.md in its URL.
- Very specific: line 156
After grit update, regenerate completions so new commands appear.
- Distinctive: line 176
If you already have a Rust toolchain:
- Very specific: line 186
After a script install, run grit update to re-run the same installer and replace the binary you're running.
- Distinctive: line 220
Every commit records an author.
- Very specific: line 274
Look at the history with grit log:
- Very specific: line 283
Create a branch and switch to it with grit switch -c:
- Very specific: line 367
If someone pushed before you, grit push is rejected and tells you what to do:
- Very specific: line 393
Every command takes --json and prints a single JSON object, which is handy for scripts and agents.
- Distinctive: line 407
Every command has a man page with its options and examples.
- Distinctive: line 432
Use the latest version on crates.io if the number above is stale.
- Very specific: line 525
Test-only knobs (GIT_TEST_NO_WRITE_REV_INDEX, GIT_TEST_MIDX_WRITE_REV, GIT_TEST_REFTABLE_AUTOCOMPACTION, GIT_TEST_DATE_NOW, and related …
- Very specific: line 573
Use --filter with a jq-like expression to narrow the JSON without piping through jq.
- Very specific: line 610
If --filter is set, it runs on {"error": "…"} like any other JSON value.
- Very specific: line 738
Use --ref-format reftable to initialize with Git's reftable ref backend (requires a reftable-capable Git for interoperability).
- Distinctive: line 750
Start a new project in a new directory:
- Distinctive: line 763
Create a bare repository to use as a shared remote:
- Distinctive: line 982
Check from a script whether the working tree is clean:
- Distinctive: line 1121
Use a different email address in one repository:
- Very specific: line 1268
When a merge is in progress (MERGE_HEAD is present) and every conflict is resolved in the index, grit commit records a merge commit with …
- Distinctive: line 1547
When there's more history, the last line shows the command for the next page.
- Distinctive: line 2015
If the current branch already has everything, nothing changes.
- Very specific: line 2016
If the current branch has no commits of its own since they diverged, it's moved forward to <branch> (a fast-forward).
- Very specific: line 2021
If both sides changed the same lines, grit lists the conflicting files, exits with an error, and leaves the branch and working tree exactly …
- Distinctive: line 2041
When both branches change the same lines:
- Distinctive: line 2051
When an untracked file would be overwritten:
- Distinctive: line 2533
When someone else pushed first:
- Distinctive: line 2867
Read the start of it:
≈ “Common” is an estimate: at least 1 in 5 of the 3,592 llms.txt files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
# https://grit-scm.com/docs/index.md
# Docs
> How to use grit, a simple Git client built on grit-lib. Start with the tutorial, then look up any command or open the library guide.
Grit is two things:
- **`grit`** — a Git client with a small, modern command line. It works on any Git repository and talks to any Git remote, but its commands are its own: one obvious way to do the common thing, plain-language output, and `--json` on every command.
- **`grit-lib`** — a fast, linkable Git library for Rust. Everything the CLI does goes through the library; you can embed the same engine in your own tools.
## How these docs are organized
| Section | What you'll find |
| --- | --- |
| **Getting started** | [Install](https://grit-scm.com/docs/install/index.md) grit, follow the [tutorial](https://grit-scm.com/docs/tutorial/index.md), or try the [library quick start](https://grit-scm.com/docs/library-quickstart/index.md). |
| **The grit CLI** | [Global options](https://grit-scm.com/docs/global-options/index.md), [scripting with `--json`](https://grit-scm.com/docs/scripting/index.md), [agent guide](https://grit-scm.com/docs/agents/index.md), and a man page for every command. |
| **Library guide** | Rust-oriented guides for `grit-lib` (growing over time), plus the [API reference on docs.rs](https://docs.rs/grit-lib). |
| **Benchmarks** | How `grit` and `grit-lib` compare to system Git on core operations. |
If you're new to the command line, start with the [tutorial](https://grit-scm.com/docs/tutorial/index.md). If you're wiring Git into a Rust program, start with the [library quick start](https://grit-scm.com/docs/library-quickstart/index.md) and the [library guide overview](https://grit-scm.com/docs/library/index.md).
## CLI vs library
Use **`grit`** when you want a day-to-day Git client from the terminal or in scripts (`--json` / `--filter`). Use **`grit-lib`** when you need programmatic access — opening repositories, reading objects and refs, diffing, revwalking, fetch/push, and the rest of Git's core — inside a Rust binary or service.
On-disk formats and the wire protocol stay compatible with Git; the CLI's argv and messages are deliberately *not* a Git mirror.
See [Install](https://grit-scm.com/docs/install/index.md) for download options, [Global options](https://grit-scm.com/docs/global-options/index.md) for flags shared by every command, [Scripting with grit](https://grit-scm.com/docs/scripting/index.md) for `--json` and `--filter`, and the [Agent guide](https://grit-scm.com/docs/agents/index.md) for automation-focused details.
## For agents
- [grit-cli.md](https://grit-scm.com/docs/grit-cli.md): the whole CLI in one file, to learn grit for everyday Git work.
- [grit-lib.md](https://grit-scm.com/docs/grit-lib.md): the whole library guide in one file, to build Git-compatible Rust programs.
- [llms.txt](https://grit-scm.com/llms.txt): an index of every page with a one-line summary.
- [llms-full.txt](https://grit-scm.com/llms-full.txt): every docs page in one file.
Every page also has a Markdown twin: replace `index.html` with `index.md` in its URL. Run `grit skill` to print an agent skill for the CLI.
## Commands
### Getting started
| Command | Summary |
| --- | --- |
| [`grit init`](https://grit-scm.com/docs/init/index.md) | Create a new, empty repository. |
| [`grit clone`](https://grit-scm.com/docs/clone/index.md) | Copy a remote repository into a new directory. |
| [`grit status`](https://grit-scm.com/docs/status/index.md) | Show where you are and what's changed. This is what plain grit runs. |
| [`grit config`](https://grit-scm.com/docs/config/index.md) | Read, set, list or remove configuration values. |
### Making changes
| Command | Summary |
| --- | --- |
| [`grit add`](https://grit-scm.com/docs/add/index.md) | Stage changes. With no paths, stages everything. |
| [`grit commit`](https://grit-scm.com/docs/commit/index.md) | Stage every change and record a new commit. |
| [`grit diff`](https://grit-scm.com/docs/diff/index.md) | Show uncommitted changes, or the change a commit introduced. |
| [`grit restore`](https://grit-scm.com/docs/restore/index.md) | Restore working tree and/or index paths from HEAD, the index, or another revision. |
### History
| Command | Summary |
| --- | --- |
| [`grit log`](https://grit-scm.com/docs/log/index.md) | Show recent commits, newest first, a page at a time. |
| [`grit shortlog`](https://grit-scm.com/docs/shortlog/index.md) | List the commits on this branch that aren't on the target branch yet. |
| [`grit show`](https://grit-scm.com/docs/show/index.md) | Show a commit, tag or branch, and a summary of what it changed. |
### Branches and tags
| Command | Summary |
| --- | --- |
| [`grit branch`](https://grit-scm.com/docs/branch/index.md) | List branches, or create or delete one. |
| [`grit switch`](https://grit-scm.com/docs/switch/index.md) | Switch to another branch, or create one and switch to it. |
| [`grit merge`](https://grit-scm.com/docs/merge/index.md) | Merge another branch into the current one. |
| [`grit pick`](https://grit-scm.com/docs/pick/index.md) | Copy a single commit onto the current branch. |
| [`grit tag`](https://grit-scm.com/docs/tag/index.md) | List tags, or create or delete one. A new tag points at the current commit. |
### Remotes
| Command | Summary |
| --- | --- |
| [`grit remote`](https://grit-scm.com/docs/remote/index.md) | List remotes, add one, or list refs on a remote. |
| [`grit fetch`](https://grit-scm.com/docs/fetch/index.md) | Download new commits, branches and tags from a remote. |
| [`grit pull`](https://grit-scm.com/docs/pull/index.md) | Fetch from the remote and bring the current branch up to date. |
| [`grit push`](https://grit-scm.com/docs/push/index.md) | Publish the current branch, or your tags, to a remote. |
| [`grit auth`](https://grit-scm.com/docs/auth/index.md) | Sign in to GitHub so HTTPS pushes and fetches just work. |
| [`grit bundle`](https://grit-scm.com/docs/bundle/index.md) | Create, verify, and list git bundle files for offline transfer. |
### Maintenance
| Command | Summary |
| --- | --- |
| [`grit update`](https://grit-scm.com/docs/update/index.md) | Update grit to the latest release. |
| [`grit skill`](https://grit-scm.com/docs/skill/index.md) | Print an agent skill that explains how to use grit. |
| [`grit completions`](https://grit-scm.com/docs/completions/index.md) | Generate shell completion scripts for bash, zsh, and fish. |
### Plumbing
| Command | Summary |
| --- | --- |
| [`grit upload-pack`](https://grit-scm.com/docs/upload-pack/index.md) | Serve a fetch or clone of a repository over stdin and stdout. |
| [`grit receive-pack`](https://grit-scm.com/docs/receive-pack/index.md) | Accept a push to a repository over stdin and stdout. |
| [`grit manager`](https://grit-scm.com/docs/manager/index.md) | A credential helper that stores passwords and tokens in the Windows Credential Manager. |
# https://grit-scm.com/docs/install/index.md
# Install grit
> Install the grit CLI on your machine, try nightly builds, and keep your copy up to date.
## Stable release (recommended)
On macOS and Linux:
```bash
curl -fsSL https://grit-scm.com/install | sh
```
On Windows, run this in PowerShell:
```bash
irm https://grit-scm.com/install.ps1 | iex
```
The script downloads the latest release from GitHub, installs the `grit` binary (by default into `~/.local/bin` on Unix), and prints the version it installed.
## Shell completions
Tab completion helps you discover `grit`'s subcommands and flags. Generate a script with [`grit completions`](https://grit-scm.com/docs/completions/index.md) and load it from your shell config, or copy the pre-generated files from a release tarball's `completions/` directory.
**bash** — add to `~/.bashrc`:
```bash
eval "$(grit completions bash)"
```
**zsh** — add to `~/.zshrc`:
```bash
eval "$(grit completions zsh)"
```
Or install once under a site-functions directory:
```bash
grit completions zsh > ~/.local/share/zsh/site-functions/_grit
```
**fish** — write a completion file:
```bash
mkdir -p ~/.config/fish/completions
grit completions fish > ~/.config/fish/completions/grit.fish
```
After [`grit update`](https://grit-scm.com/docs/update/index.md), regenerate completions so new commands appear.
## Nightly builds
CI publishes a rolling **nightly** prerelease when the release workflow is triggered manually. To install that build instead of the latest stable release:
```bash
curl -fsSL https://grit-scm.com/install-nightly | sh
```
On Windows:
```bash
irm https://grit-scm.com/install-nightly.ps1 | iex
```
Nightlies track recent `main`; use them when you want to test fixes before the next tagged release.
## Install with Cargo
If you already have a Rust toolchain:
```bash
cargo install grit-cli
```
This builds and installs the `grit` executable into Cargo's bin directory (usually `~/.cargo/bin`). Make sure that directory is on your `PATH`.
## Keep grit up to date
After a script install, run [`grit update`](https://grit-scm.com/docs/update/index.md) to re-run the same installer and replace the binary you're running. If you installed with Cargo, update with:
```bash
cargo install grit-cli
```
## Build from source
Clone [the repository](https://github.com/gitbutlerapp/grit) and build the CLI crate:
```bash
cargo build --release -p grit-cli
```
The binary is `target/release/grit`. You can copy it anywhere on your `PATH`, or run it from the build tree.
### Toolchain
The workspace pins a Rust version in [`rust-toolchain.toml`](https://github.com/gitbutlerapp/grit/blob/main/rust-toolchain.toml) (currently **1.99.0** with `rustfmt` and `clippy`). `rustup` picks this up automatically when you build in the repo.
To use `grit-lib` in your own crate, add it from [crates.io](https://crates.io/crates/grit-lib) — see the [library quick start](https://grit-scm.com/docs/library-quickstart/index.md).
# https://grit-scm.com/docs/tutorial/index.md
# Tutorial
> Fifteen minutes with grit. Create a repository, record some changes, work on a branch, and share it with a remote.
This walkthrough covers the commands you'll use every day. It assumes you have [installed grit](https://grit-scm.com/docs/install/index.md) and know roughly what a commit and a branch are. The output shown is what `grit` prints, minus the colors.
Regenerated on 2026-10-07 by running the listed commands with `grit` built from this repository (`cargo build --release -p grit-cli`), with `NO_COLOR=1` and author identity `Ada Lovelace <ada@example.com>`.
## Tell grit who you are
Every commit records an author. Set your name and email once, in your global config:
```console
$ grit config --global user.name "Ada Lovelace"
$ grit config --global user.email ada@example.com
```
`grit` reads and writes the same config files as Git, so if you've already set these up for Git, you can skip this step.
## Create a repository
```console
$ grit init project
Initialized empty repository in /workspace/project/.git
$ cd project
```
To work on an existing project instead, copy it with [`grit clone`](https://grit-scm.com/docs/clone/index.md) and skip ahead to the next section:
```console
$ grit clone https://github.com/gitbutlerapp/grit.git
```
## Your home base: grit status
Running `grit` with no arguments shows where you are and what's changed. Add a couple of files and look:
```console
$ echo "# Notes" > README.md
$ echo "fn main() {}" > main.rs
$ grit
On main — no commits yet
Untracked
? untracked README.md
? untracked main.rs
→ grit add <file> to stage
```
The last line always suggests the next step. You'll come back to this screen a lot; [`grit status`](https://grit-scm.com/docs/status/index.md) (or `grit st`) shows the same thing.
## Record a commit
[`grit commit`](https://grit-scm.com/docs/commit/index.md) stages every change in the working tree and records it in one step:
```console
$ grit commit "Start the project"
[main 310fdb0] Start the project
2 changes committed
```
There is no separate staging step to remember. [`grit add`](https://grit-scm.com/docs/add/index.md) exists for when you want to stage particular files and check them in `grit status` first, but `grit commit` always records every change.
Look at the history with [`grit log`](https://grit-scm.com/docs/log/index.md):
```console
$ grit log
310fdb0 ada just now Start the project
```
## Work on a branch
Create a branch and switch to it with [`grit switch -c`](https://grit-scm.com/docs/switch/index.md):
```console
$ grit switch -c feature
Created and switched to branch feature
```
Make a change and look at it with [`grit diff`](https://grit-scm.com/docs/diff/index.md) before committing:
```console
$ printf 'fn main() {\n println!("hi");\n}\n' > main.rs
$ grit diff
main.rs
@@ -1 +1 @@
1 │ - fn main() {}
1 │ + fn main() {
2 │ + println!("hi");
3 │ + }
```
The two number columns are the old and new line numbers. Commit the change:
```console
$ grit commit "Say hi"
[feature 2e409e2] Say hi
1 change committed
```
[`grit show`](https://grit-scm.com/docs/show/index.md) displays a commit, its message and the files it changed. With no argument, it shows the latest commit:
```console
$ grit show
branch feature
commit 2e409e26f8b370ea1928a8fb93dcf2e025418e1f
Author: Ada Lovelace <ada@example.com>
Date: 2026-10-07 14:55:47 +0000
Say hi
main.rs | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
```
## Merge it back
Switch back to `main` and [merge](https://grit-scm.com/docs/merge/index.md) the branch in. Nothing else has happened on `main`, so `grit` just moves `main` forward:
```console
$ grit switch main
Switched to branch main
$ grit merge feature
Fast-forwarded feature → 2e409e2
```
The branch is done, so [delete it](https://grit-scm.com/docs/branch/index.md):
```console
$ grit branch -d feature
Deleted branch feature (was 2e409e2).
```
`grit branch -d` refuses to delete a branch whose commits haven't been merged into the branch you're on. Use `-D` when you really mean it.
## Share it with a remote
A remote is another copy of the repository, usually on a server. Add one called `origin` with [`grit remote add`](https://grit-scm.com/docs/remote/index.md), then [push](https://grit-scm.com/docs/push/index.md):
```console
$ grit remote add origin https://github.com/ada/project.git
Added remote origin → https://github.com/ada/project.git
$ grit push
pushed main → origin refs/heads/main
```
`grit push` sends the current branch to a branch with the same name on `origin`, creating it if needed. There are no upstream flags to set. For GitHub over HTTPS, [`grit auth`](https://grit-scm.com/docs/auth/index.md) signs you in, and `grit` offers to run it if a push fails for lack of credentials.
To get other people's work, run [`grit pull`](https://grit-scm.com/docs/pull/index.md). It fetches from the remote and brings your branch up to date, fast-forwarding when it can and recording a merge commit when both sides have new commits:
```console
$ grit pull
Merged origin/main into the current branch (91275a2)
```
If someone pushed before you, `grit push` is rejected and tells you what to do:
```console
$ grit push
rejected origin refs/heads/main: not a fast-forward — run `grit pull` first
```
## Tag a release
[`grit tag`](https://grit-scm.com/docs/tag/index.md) marks the current commit, and `grit push --tags` publishes your tags:
```console
$ grit tag v0.1
Created tag v0.1
$ grit push --tags
pushed --tags → origin refs/tags/v0.1
```
## When things conflict
`grit merge`, `grit pull` and `grit pick` never leave a half-finished merge behind. If the two sides change the same lines, `grit` lists the conflicting files and leaves your branch and working tree as they were. To resolve the conflict, run the merge with `git`, fix the files and commit. Conflict resolution in `grit` itself is on the roadmap.
`grit` also refuses to switch branches, merge or pull while you have uncommitted changes, so work in progress can't get mixed into a merge. Commit first.
## Scripting
Every command takes `--json` and prints a single JSON object, which is handy for scripts and agents. `--filter` picks out the part you need:
```console
$ grit status --json --filter '{branch, clean}'
{
"branch": "main",
"clean": true
}
```
See [Scripting with grit](https://grit-scm.com/docs/scripting/index.md) for details, and each command's page for its JSON fields.
## Where to go next
Every command has a man page with its options and examples. Start from the [command list](https://grit-scm.com/docs/index.md#commands).
# https://grit-scm.com/docs/library-quickstart/index.md
# Library quick start
> Add grit-lib to a Rust project, open a repository, and read the current commit from HEAD.
This page walks through a minimal program that discovers a Git repository in the current directory (or a parent), resolves `HEAD`, and prints the commit id and subject line. The source below is the real example binary in the Grit repository; it is included automatically so the docs cannot drift from compiled code.
## Add the dependency
In your crate:
```bash
cargo add grit-lib
```
Or add to `Cargo.toml`:
```toml
[dependencies]
grit-lib = "0.5.0"
```
Use the [latest version on crates.io](https://crates.io/crates/grit-lib) if the number above is stale.
## Example program
Save as `src/main.rs` (or copy from `grit-examples` in the Grit repo):
```rust
//! Minimal grit-lib program: discover a repository and print HEAD's commit id.
//!
//! Source for the library quick start in the docs; kept in sync via an include directive.
use grit_lib::objects::{parse_commit, ObjectKind};
use grit_lib::repo::Repository;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let repo = Repository::discover(None)?;
let head = grit_lib::refs::resolve_ref(&repo.git_dir, "HEAD")?;
let object = repo.odb.read(&head)?;
if object.kind != ObjectKind::Commit {
return Err("HEAD is not a commit".into());
}
let commit = parse_commit(&object.data)?;
println!("{head}");
let subject = commit.message.lines().next().unwrap_or("");
if !subject.is_empty() {
println!("{subject}");
}
Ok(())
}
```
## Run it
From the root of any Git repository with at least one commit:
```bash
cargo run
```
Example output (your commit id will differ):
```text
217c6f9a1b2c3d4e5f6789012345678901234567
Start the project
```
The first line is the full object id of `HEAD`; the second is the first line of the commit message.
## Next steps
- [Library guide overview](https://grit-scm.com/docs/library/index.md) — longer-form guides for objects, refs, diff, and network code.
- [grit-lib on docs.rs](https://docs.rs/grit-lib) — API reference for `Repository` and the rest of the public surface.
- [Tutorial](https://grit-scm.com/docs/tutorial/index.md) — the same repository operations from the `grit` CLI.
# https://grit-scm.com/docs/global-options/index.md
# Global options
> Options that apply to every grit command.
These options work on any command (and on `grit` itself when you pass no subcommand).
| Option | Description |
| --- | --- |
| `--json` | Print one JSON object instead of human-readable text. Errors become `{"error": "..."}`. |
| `--markdown` | Print agent-friendly Markdown instead of human-readable text. Most commands render structured headings, lists, and tables (or fenced diffs) rather than dumping JSON. Mutually exclusive with `--json`. |
| `--filter <EXPR>` | Apply a jq expression to the JSON output. Requires `--json`. |
| `-h`, `--help` | Print help for `grit` or for a command. |
| `-V`, `--version` | Print the version of `grit`. |
Running `grit` with no command is the same as [`grit status`](https://grit-scm.com/docs/status/index.md).
## Environment variables
The `grit` CLI snapshots the process environment into [`Environment`](https://grit-scm.com/docs/library/repository/index.md) when opening a repository. Library embedders should construct an [`Environment`](https://grit-scm.com/docs/library/repository/index.md) explicitly instead of relying on these variables.
| Variable | Effect |
| --- | --- |
| `GIT_DIR`, `GIT_WORK_TREE`, `GIT_CEILING_DIRECTORIES`, `GIT_PREFIX` | Repository discovery |
| `GIT_INDEX_FILE`, `GIT_OBJECT_DIRECTORY`, `GIT_ALTERNATE_OBJECT_DIRECTORIES` | Index and object store paths |
| `GIT_CONFIG`, `GIT_CONFIG_GLOBAL`, `GIT_CONFIG_SYSTEM`, `GIT_CONFIG_NOSYSTEM`, `GIT_CONFIG_COUNT`, `GIT_CONFIG_KEY_n`, `GIT_CONFIG_VALUE_n`, `GIT_CONFIG_PARAMETERS` | Config cascade |
| `HOME`, `XDG_CONFIG_HOME`, `USERPROFILE`, `USER`, `USERNAME` | Home and identity fallbacks |
| `GIT_AUTHOR_*`, `GIT_COMMITTER_*` | Author/committer name, email, and date overrides for new objects |
| `GIT_SSH`, `GIT_SSH_COMMAND` | SSH transport command |
| `GIT_HTTP_LOW_SPEED_LIMIT`, `GIT_HTTP_LOW_SPEED_TIME` | HTTP low-speed abort thresholds |
| `GIT_NOTES_REF`, `GIT_NOTES_DISPLAY_REF` | Notes ref selection |
| `GIT_ATTR_SOURCE`, `GIT_INDEX_VERSION`, `GIT_PRINT_SHA1_ELLIPSIS` | Attributes, index format, diff OID display |
| `GIT_NAMESPACE`, `GIT_REPLACE_REF_BASE`, `GIT_NO_REPLACE_OBJECTS` | Ref namespaces and replace refs |
| `GIT_TRACE`, `GIT_TRACE_SETUP`, `GIT_TRACE2_PERF` | Trace output |
| `PATH` | Helper lookup (e.g. signing programs) |
| `TZ` | Local timezone for dates when no explicit offset is given |
| `GIT_EXEC_PATH`, `GIT_INSTALL_ROOT` | Git helper discovery (credentials) |
Test-only knobs (`GIT_TEST_NO_WRITE_REV_INDEX`, `GIT_TEST_MIDX_WRITE_REV`, `GIT_TEST_REFTABLE_AUTOCOMPACTION`, `GIT_TEST_DATE_NOW`, and related values) are parsed into typed [`Environment`](https://grit-scm.com/docs/library/repository/index.md) fields when present; they are not read elsewhere in `grit-lib`.
# https://grit-scm.com/docs/scripting/index.md
# Scripting with grit
> Use --json and --filter to build scripts on top of grit.
With `--json`, a command prints exactly one JSON value on stdout, so you can pipe it straight into other tools. The shape of each command's output is documented on its page. `--filter` runs a [jq](https://jqlang.org) expression over that value without needing `jq` installed. When a filter produces several values, they come back as one JSON array:
```console
$ grit status --json --filter '{branch, clean}'
{
"branch": "main",
"clean": true
}
$ grit log --json --filter '.commits[].subject'
[
"Say hi",
"Start the project"
]
```
`grit` exits with status `0` on success and `1` when a command fails (including a push with a rejected ref). A mistake on the command line, such as an unknown option, exits with `2`.
Color is used only when stdout is a terminal. Set `NO_COLOR` to turn it off.
For autonomous agents — non-interactive auth, where to find `llms.txt`, and a fuller JSON contract — see the [Agent guide](https://grit-scm.com/docs/agents/index.md).
# https://grit-scm.com/docs/agents/index.md
# Agent guide
> Run grit from scripts and autonomous agents — JSON output, exit codes, non-interactive use, credentials, and where to read the docs.
This page is for programs and agents that drive [`grit`](https://grit-scm.com/docs/install/index.md) in automation. It describes **existing** CLI behavior only. For field-level JSON schemas, use each command's docs page; this guide covers the shared contract.
Examples below were captured on 2026-10-08 with `grit` built from this repository (`cargo build --release -p grit-cli`), in a temporary repository on branch `main`, unless noted.
## Prefer `--json` (and `--filter`)
Pass **`--json`** on every command when something other than a human reads the result. In that mode:
- **stdout** carries exactly **one** JSON value: the command's outcome object on success, or `{"error": "…"}` on failure.
- **stderr** carries progress lines, auth prompts, and human-style `error: …` diagnostics. Parsers should read **stdout only** for the outcome.
- The process still exits non-zero on failure, so you can branch on the exit code **or** the presence of an `error` key.
Use **`--filter`** with a [jq](https://jqlang.org)-like expression to narrow the JSON without piping through `jq`. It requires `--json`. Multiple filter results become one JSON array.
```console
$ grit status --json --filter '{branch, clean}'
{
"branch": "main",
"clean": false
}
$ grit log --json --filter '.commits[].subject'
[
"Say hi",
"Start the project"
]
```
Plain `grit` with no subcommand is the same as [`grit status`](https://grit-scm.com/docs/status/index.md); `--json` works there too:
```console
$ grit --json --filter '{branch, clean}'
{
"branch": "main",
"clean": false
}
```
See [Scripting with grit](https://grit-scm.com/docs/scripting/index.md) for more `--filter` patterns. Per-command keys are documented under [The grit CLI](https://grit-scm.com/docs/global-options/index.md) command pages.
## Error object shape
On failure with `--json`, stdout is a single object with an **`error`** string (the same message a human sees after `error:` on stderr):
```console
$ grit commit --json
{"error":"provide a commit message, e.g. grit commit \"what changed\""}
```
If `--filter` is set, it runs on `{"error": "…"}` like any other JSON value. A bad filter expression also yields `{"error": "…"}` on stdout:
```console
$ grit status --json --filter 'invalid!!!'
{"error":"invalid filter \"invalid!!!\": [(File { code: \"invalid!!!\", path: () }, Parse([(Nothing, \"!!!\")]))]"}
```
In **human** mode, errors print to **stderr** and stdout stays empty:
```console
$ grit commit
error: provide a commit message, e.g. grit commit "what changed"
```
## Exit codes
| Code | Meaning |
| --- | --- |
| **0** | Success (including some jq filters that evaluate to `null` when a path is missing). |
| **1** | Command failed (missing repo, rejected push, validation error, and similar). With `--json`, stdout still contains `{"error": "…"}`. |
| **2** | Usage error (unknown option or subcommand). Clap prints help to stderr; there is no JSON error object on stdout. |
```console
$ grit --nope
error: unexpected argument '--nope' found
Usage: grit [OPTIONS] [COMMAND]
For more information, try '--help'.
```
```console
$ grit status --filter '.branch'
error: --filter requires --json
```
[`grit push`](https://grit-scm.com/docs/push/index.md) can exit **1** even after printing a full JSON outcome when a ref was rejected (same idea as Git: the outcome is reported, but the operation failed).
## Color and terminal detection
Human output uses ANSI color only when **stdout is a terminal**, the environment supports ANSI (`grit_lib::terminal::ansi_supported()`), and **`NO_COLOR` is unset** ([no-color.org](https://no-color.org)). Piped or redirected stdout is plain text; set `NO_COLOR=1` to force plain text on a TTY.
JSON mode never depends on color; always pass `--json` for machines.
## Stay non-interactive
`grit` does **not** open an external editor for commit messages. [`grit commit`](https://grit-scm.com/docs/commit/index.md) requires a message on the command line (positional or `-m`); there is no `$GIT_EDITOR` path.
Commands and flows that can **block on a person**:
| Area | Behavior | How to avoid blocking |
| --- | --- | --- |
| [`grit auth`](https://grit-scm.com/docs/auth/index.md) | OAuth device flow: instructions on stderr, then polls GitHub until you authorize in a browser. | Run `grit auth` once in an interactive session before automation. Store the token via `credential.helper` (see below). |
| [`grit fetch`](https://grit-scm.com/docs/fetch/index.md) / [`grit push`](https://grit-scm.com/docs/push/index.md) / [`grit pull`](https://grit-scm.com/docs/pull/index.md) | On HTTPS `github.com` auth failure, if **stdin is a TTY**, grit may ask `Sign in to GitHub now? [Y/n]` and run the device flow. | Use a stored token from `grit auth`, or ensure stdin is not a TTY so grit prints a hint and exits without prompting. |
| [`grit clone`](https://grit-scm.com/docs/clone/index.md) / [`grit fetch`](https://grit-scm.com/docs/fetch/index.md) / [`grit pull`](https://grit-scm.com/docs/pull/index.md) / [`grit push`](https://grit-scm.com/docs/push/index.md) over **SSH** | Grit runs `ssh` with protocol stdin/stdout piped but **stderr inherited**, so the SSH child can still talk to `/dev/tty` (host-key confirmation, passphrase prompts, `ssh-askpass`, and similar). `--json` does not disable this. | Preconfigure keys and known hosts; for unattended jobs set `GIT_SSH_COMMAND='ssh -o BatchMode=yes'` so SSH fails fast instead of prompting (grit resolves SSH from `GIT_SSH_COMMAND`, then `GIT_SSH`, then `ssh` on `PATH` — not `core.sshCommand`). |
| [`grit update`](https://grit-scm.com/docs/update/index.md) | Runs the release installer (`curl \| sh` on Unix). | Do not invoke in unattended jobs unless you intend to upgrade the binary. |
There is no global `--yes` flag. For commits, always pass `-m` / a message argument.
[`grit auth logout`](https://grit-scm.com/docs/auth/index.md) is non-interactive and reports whether a helper had a token to erase:
```console
$ grit auth logout --json
{
"logged_out": false,
"host": "github.com"
}
```
### Plumbing commands (not JSON)
These speak binary or line protocols on stdin/stdout and have **no** `--json` mode: [`grit manager`](https://grit-scm.com/docs/manager/index.md), [`grit upload-pack`](https://grit-scm.com/docs/upload-pack/index.md), [`grit receive-pack`](https://grit-scm.com/docs/receive-pack/index.md). Agents should not wrap them as JSON commands.
`-V` / `--version` prints a version string and does not emit JSON even if `--json` is passed:
```console
$ grit --json --version
grit 0.5.1
```
## Credentials (HTTPS GitHub)
For `https://github.com` remotes, sign in once with [`grit auth`](https://grit-scm.com/docs/auth/index.md). Grit uses GitHub's device flow, then stores an access token through your configured **`credential.helper`** (same mechanism as Git). Override the OAuth app id with `GRIT_GITHUB_CLIENT_ID` or `grit config --global grit.githubClientId …`.
Sign out with `grit auth logout`. You need a credential helper configured (for example `grit config --global credential.helper store` on Linux — see the [`grit auth`](https://grit-scm.com/docs/auth/index.md) page).
SSH remotes do not use the GitHub device-flow token; they can still block on SSH prompts (see the SSH row above).
## Documentation for agents
| Resource | URL / path | Use |
| --- | --- | --- |
| **Agent skill** | [`grit skill`](https://grit-scm.com/docs/skill/index.md) | A `SKILL.md` for coding agents, printed by the installed binary: `grit skill > .agents/skills/grit/SKILL.md`. |
| **llms.txt** | [grit-scm.com/llms.txt](https://grit-scm.com/llms.txt) | Curated index of every docs page (llmstxt.org format). |
| **llms-full.txt** | [grit-scm.com/llms-full.txt](https://grit-scm.com/llms-full.txt) | Full text of all docs Markdown twins in site order. |
| **Markdown twin** | Same URL as HTML but `index.md` instead of `index.html` (e.g. [status/index.md](https://grit-scm.com/docs/status/index.md)) | One page per command or guide; linked from HTML as "Markdown". |
| **Command JSON fields** | Under [The grit CLI](https://grit-scm.com/docs/global-options/index.md) | Each command page lists real `--json` examples and field tables. |
| **grit-lib API** | [docs.rs/grit-lib](https://docs.rs/grit-lib) | Rust library reference when embedding grit in your own binary. |
| **Library guide** | [Library guide](https://grit-scm.com/docs/library/index.md) | Narrative Rust workflows on top of `grit-lib`. |
Site generation keeps `docs/llms.txt` and `docs/llms-full.txt` in the repository in sync with [site.toml](https://github.com/gitbutlerapp/grit/blob/main/content/docs/site.toml); after local doc edits, run `make docs`.
## See also
- [Scripting with grit](https://grit-scm.com/docs/scripting/index.md) — `--json`, `--filter`, and exit codes in brief
- [Global options](https://grit-scm.com/docs/global-options/index.md) — flags shared by every command
- [Docs overview](https://grit-scm.com/docs/index.md) — how the site is organized
# https://grit-scm.com/docs/init/index.md
# grit init
> Create a new, empty repository.
## Synopsis
```text
grit init [--bare] [--ref-format <files|reftable>] [<path>]
```
Global options [`--json`](https://grit-scm.com/docs/global-options/index.md) and [`--markdown`](https://grit-scm.com/docs/global-options/index.md) apply.
## Description
Creates an empty Git repository at `<path>`, or in the current directory when no path is given. The directory is created if it doesn't exist. A normal repository keeps its data in a `.git` directory next to your files. A bare repository has no working tree; the repository data is the directory itself, which is what you want for a repository that other people push to.
The first branch is `main`. It has no commits until you make one.
Use `--ref-format reftable` to initialize with Git's reftable ref backend (requires a reftable-capable Git for interoperability). The default is `files` (loose refs under `refs/`).
## Options
| Option | Description |
| --- | --- |
| `<path>` | Where to create the repository. Defaults to the current directory. |
| `--bare` | Create a bare repository, with no working tree. |
| `--ref-format` | Ref storage backend: `files` (default) or `reftable`. |
## Examples
Start a new project in a new directory:
```console
$ grit init project
Initialized empty repository in /home/ada/project/.git (ref-format: files)
```
Turn the current directory into a repository:
```console
$ grit init
```
Create a bare repository to use as a shared remote:
```console
$ grit init --bare /srv/git/project.git
Initialized empty bare repository in /srv/git/project.git (ref-format: files)
```
Initialize with the reftable ref backend:
```console
$ grit init --ref-format reftable reftable-demo
Initialized empty repository in /home/ada/reftable-demo/.git (ref-format: reftable)
```
## JSON output
Pass `--json` for stable, scripting-friendly output:
| Field | Type | Meaning |
| ----- | ---- | ------- |
| `initialized` | boolean | Whether the repository was created successfully. |
| `path` | string | Repository directory (the `.git` directory for a normal repository). |
| `bare` | boolean | Whether the repository is bare. |
| `branch` | string | Initial branch name. |
| `ref_format` | string | Ref storage backend (`files` or `reftable`). |
Example:
```json
{
"initialized": true,
"path": "/home/ada/project/.git",
"bare": false,
"branch": "main",
"ref_format": "files"
}
```
## Markdown output
Pass [`--markdown`](https://grit-scm.com/docs/global-options/index.md) for a short prose summary:
```text
Initialized empty repository at `/home/ada/project/.git` (default branch `main`, ref-format `reftable`).
```
## See also
[grit clone](https://grit-scm.com/docs/clone/index.md), [grit remote](https://grit-scm.com/docs/remote/index.md)
# https://grit-scm.com/docs/clone/index.md
# grit clone
> Copy a remote repository into a new directory.
## Synopsis
```text
grit clone <url> [<dir>]
```
## Description
Copies the repository at `<url>` into a new directory and checks out the remote's default branch. The remote is saved as `origin`, so [`grit fetch`](https://grit-scm.com/docs/fetch/index.md), [`grit pull`](https://grit-scm.com/docs/pull/index.md) and [`grit push`](https://grit-scm.com/docs/push/index.md) work with no further setup.
`<url>` can be an `https://` or `http://` URL, an `ssh://` URL or `user@host:path` address, a `git://` URL, a `file://` URL, a path to a local repository, or a path to a [git bundle](https://git-scm.com/docs/git-bundle) file (recognized by its header signature). A local path is stored as an absolute path so that later fetches work from anywhere.
Without `<dir>`, the directory is named after the last part of the URL with any `.git` suffix removed, so `https://github.com/gitbutlerapp/grit.git` clones into `grit`. The destination must not exist or must be empty.
For private GitHub repositories over HTTPS, sign in first with [`grit auth`](https://grit-scm.com/docs/auth/index.md).
You can clone from a shallow repository (including one created with `git clone --depth`); grit copies the shallow boundary into the new repository so history matches the source.
## Options
| Option | Description |
| --- | --- |
| `<url>` | The repository to clone: a URL or a local path. |
| `<dir>` | The directory to clone into. Defaults to the repository's name. |
## Examples
Clone a repository from GitHub:
```console
$ grit clone https://github.com/gitbutlerapp/grit.git
Cloning into 'grit' ...
Cloned into 'grit' on branch main.
```
Clone into a directory with a different name:
```console
$ grit clone git@github.com:gitbutlerapp/grit.git grit-src
```
Clone a local repository:
```console
$ grit clone /srv/git/project.git
```
## JSON output
Pass `--json` for stable, scripting-friendly output:
| Field | Type | Meaning |
| ----- | ---- | ------- |
| `url` | string | The URL or path that was cloned. |
| `path` | string | Directory the clone was created in. |
| `branch` | string | Branch that was checked out. |
Example:
```json
{
"url": "/srv/git/project.git",
"path": "project",
"branch": "main"
}
```
## See also
[grit init](https://grit-scm.com/docs/init/index.md), [grit remote](https://grit-scm.com/docs/remote/index.md), [grit fetch](https://grit-scm.com/docs/fetch/index.md), [grit auth](https://grit-scm.com/docs/auth/index.md)
# https://grit-scm.com/docs/status/index.md
# grit status
> Show where you are and what's changed. This is what plain grit runs.
## Synopsis
```text
grit
grit status
grit st
```
## Description
The status screen is your home base. It shows, from top to bottom:
- **Where you are.** The current branch and how it compares with its target branch: how many commits ahead it is, followed by those commits (up to ten). A branch with no commits says `no commits yet`, and a detached HEAD shows the commit it's on.
- **Staged** changes, which are ready to commit.
- **Changed (not staged)** files, which have been modified since they were last staged.
- **Untracked** files, which `grit` isn't tracking yet.
- **A hint** with the next command to run.
Each change has a label: `new`, `modified`, `deleted`, `renamed`, `copied`, `type changed` or `conflict`.
Paths are shown relative to the directory you run `grit` from.
### The target branch
The target is the branch your work is headed for. `grit` uses the first of these that exists:
1. the branch named in the `target.branch` config setting
2. `origin/master`
3. `origin/main`
4. `master`
5. `main`
To compare against something else, set it for the repository:
```console
$ grit config target.branch origin/develop
```
## Options
`grit status` takes no options beyond the [global ones](https://grit-scm.com/docs/global-options/index.md).
## Examples
A branch with work in progress:
```console
$ grit
On feature · 2 ahead of origin/main
cf18394 ada 2 hours ago Say hi
9a1c2e0 ada 3 hours ago Add a greeting test
Staged
+ new notes.md
Changed (not staged)
~ modified main.rs
Untracked
? untracked scratch.txt
→ grit add <file> to stage · grit commit "message" to commit
```
Everything committed and pushed:
```console
$ grit st
On main · even with origin/main
Nothing to commit — working tree clean.
```
Merge in progress with a conflict:
```console
$ grit status
On main · merging — resolve conflicts
Staged
! conflict f
→ resolve conflicts, then grit commit "message"
```
Check from a script whether the working tree is clean:
```console
$ grit status --json --filter .clean
true
```
## JSON output
Pass `--json` for stable, scripting-friendly output:
| Field | Type | Meaning |
| ----- | ---- | ------- |
| `branch` | string or null | Current branch, or `null` when HEAD is detached. |
| `detached` | boolean | Whether HEAD is detached. |
| `head` | string or null | Full id of the current commit, or `null` before the first commit. |
| `target` | string or null | Target branch, or `null` when none was found. |
| `ahead` | number | Commits on the branch that the target does not have. |
| `commits` | array | Newest of those commits, up to ten, each with `oid` and `subject`. |
| `staged` | array | Staged changes with `path` and `status`. |
| `unstaged` | array | Unstaged changes with `path` and `status`. |
| `untracked` | array | Paths of untracked files. |
| `clean` | boolean | `true` when there is nothing to commit and nothing untracked. |
| `merging` | boolean | `true` when a merge is in progress (`MERGE_HEAD` exists). |
| `in_progress` | array | Stable operation ids while work is paused (for example `merge`, `rebase`). Omitted when empty. |
| `conflicts` | array | Paths with unmerged index stages. Omitted when empty. |
Example:
```json
{
"branch": "feature",
"detached": false,
"head": "cf18394a62c3f845bd9c44927a5a55e014b2a99d",
"target": "origin/main",
"ahead": 2,
"commits": [
{ "oid": "cf18394a62c3f845bd9c44927a5a55e014b2a99d", "subject": "Say hi" },
{ "oid": "9a1c2e0d4b6f8a1c3e5d7f9b0a2c4e6d8f0a1b3c", "subject": "Add a greeting test" }
],
"staged": [
{ "path": "notes.md", "status": "added" }
],
"unstaged": [
{ "path": "main.rs", "status": "modified" }
],
"untracked": ["scratch.txt"],
"clean": false
}
```
## Markdown output
Pass [`--markdown`](https://grit-scm.com/docs/global-options/index.md) for headed sections that mirror the status screen:
```text
On **`feature`** · **2** ahead of `origin/main`
- `cf18394` Say hi (ada, 1 hour ago)
Staged
- **new** `notes.md`
Changed (not staged)
- **modified** `main.rs`
Untracked
- `scratch.txt`
```
## See also
[grit shortlog](https://grit-scm.com/docs/shortlog/index.md), [grit diff](https://grit-scm.com/docs/diff/index.md), [grit add](https://grit-scm.com/docs/add/index.md), [grit commit](https://grit-scm.com/docs/commit/index.md)
# https://grit-scm.com/docs/config/index.md
# grit config
> Read, set, list or remove configuration values.
## Synopsis
```text
grit config [--global] <key>
grit config [--global] <key> <value>
grit config [--global] --unset <key>
grit config [--global] --list
```
## Description
Reads and writes Git configuration. `grit` uses the same config files as Git: the repository's `.git/config`, and your per-user `~/.gitconfig`. Settings you've made with Git apply to `grit`, and the other way around.
With just a key, `grit config` prints its value. Reads look at every config file, with the repository's settings taking priority over your global ones. With a key and a value, it sets the value in the repository's config. Add `--global` to read or write your per-user config instead.
Keys are written as `section.name`, for example `user.email`.
### Settings grit uses
| Key | Used for |
| --- | --- |
| `user.name`, `user.email` | The author and committer of new commits. |
| `target.branch` | The branch [`grit status`](https://grit-scm.com/docs/status/index.md) and [`grit shortlog`](https://grit-scm.com/docs/shortlog/index.md) compare against. |
| `branch.<name>.remote` | Which remote [`grit push`](https://grit-scm.com/docs/push/index.md) and [`grit pull`](https://grit-scm.com/docs/pull/index.md) use for a branch. Defaults to `origin`. |
| `branch.<name>.merge` | Which remote branch a branch pushes to and pulls from. Defaults to the same name. |
| `credential.helper` | Where HTTPS credentials are stored and looked up. See [`grit auth`](https://grit-scm.com/docs/auth/index.md). |
| `grit.githubClientId` | The GitHub OAuth app [`grit auth`](https://grit-scm.com/docs/auth/index.md) signs in with. |
| `receive.denyNonFastForwards` | Refuse pushes that would discard commits. Enforced by [`grit receive-pack`](https://grit-scm.com/docs/receive-pack/index.md). |
| `receive.denyDeletes` | Refuse pushes that delete branches or tags. |
| `receive.denyCurrentBranch` | Refuse pushes to the branch checked out in a non-bare repository. On by default. |
## Options
| Option | Description |
| --- | --- |
| `<key>` | The setting to read, set or remove. |
| `<value>` | The value to set. Omit it to read the current value. |
| `--global` | Use your per-user config (`~/.gitconfig`) instead of the repository's. |
| `-l`, `--list` | List every setting as `key=value`. |
| `--unset` | Remove the setting. |
Reading or removing a key that isn't set is an error.
## Examples
Set your identity for every repository:
```console
$ grit config --global user.name "Ada Lovelace"
$ grit config --global user.email ada@example.com
```
Read a value:
```console
$ grit config user.email
ada@example.com
```
Use a different email address in one repository:
```console
$ grit config user.email ada@work.example
```
List everything:
```console
$ grit config --list
user.name=Ada Lovelace
user.email=ada@example.com
core.repositoryformatversion=0
core.bare=false
remote.origin.url=https://github.com/ada/project.git
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
```
Remove a setting:
```console
$ grit config --unset target.branch
```
## JSON output
Pass `--json` for stable, scripting-friendly output. The object's `action` field says what happened:
| Field | Type | Meaning |
| ----- | ---- | ------- |
| `action` | string | `get`, `set`, `unset`, or `list`. |
| `key` | string | Configuration key for `get`, `set`, or `unset`. |
| `value` | string | Value for `get` or `set`. |
| `entries` | array | For `list`, each entry with `key` and optional `value`. |
Reading a value:
```json
{
"action": "get",
"key": "user.name",
"value": "Ada Lovelace"
}
```
Listing values:
```json
{
"action": "list",
"entries": [
{ "key": "user.name", "value": "Ada Lovelace" }
]
}
```
## See also
[grit auth](https://grit-scm.com/docs/auth/index.md), [grit status](https://grit-scm.com/docs/status/index.md)
# https://grit-scm.com/docs/add/index.md
# grit add
> Stage changes. With no paths, stages everything.
## Synopsis
```text
grit add [<path>...]
```
## Description
Stages changes so they show up under **Staged** in [`grit status`](https://grit-scm.com/docs/status/index.md). With no paths, `grit add` stages everything `grit status` reports: modified files, deleted files and untracked files. With paths, it stages only those files, or everything under those directories.
Paths are relative to your current directory, so from inside `src/`, `grit add main.rs` stages `src/main.rs`. Paths like `../README.md` and absolute paths inside the repository work too. A path that matches nothing is an error, and nothing is staged.
[`grit commit`](https://grit-scm.com/docs/commit/index.md) stages every change before it records a commit, so you don't need `grit add` to commit. It's useful for starting to track a new file and checking what will be committed.
## Options
| Option | Description |
| --- | --- |
| `<path>...` | Files or directories to stage. Omit to stage every change. |
## Examples
Stage everything:
```console
$ grit add
Staged 3 changes.
```
Stage one file and a directory:
```console
$ grit add README.md src/
Staged 2 changes.
```
## JSON output
Pass `--json` for stable, scripting-friendly output:
| Field | Type | Meaning |
| ----- | ---- | ------- |
| `staged` | number | How many paths were staged by this invocation. |
Example:
```json
{
"staged": 2
}
```
## See also
[grit status](https://grit-scm.com/docs/status/index.md), [grit commit](https://grit-scm.com/docs/commit/index.md)
# https://grit-scm.com/docs/commit/index.md
# grit commit
> Stage every change and record a new commit.
## Synopsis
```text
grit commit [-a] <message>
grit commit [-a] -m <message>
```
## Description
Stages every change in the working tree (modified, deleted and untracked files) and records a new commit on the current branch with the given message. This is the same as running [`grit add`](https://grit-scm.com/docs/add/index.md) followed by a commit.
The message can be given as an argument or with `-m`. A message with several lines is recorded as is; its first line is the subject that [`grit log`](https://grit-scm.com/docs/log/index.md) shows. A commit needs a message: without one, `grit commit` stages your changes and stops with an error.
The author and committer come from the `user.name` and `user.email` settings (see [`grit config`](https://grit-scm.com/docs/config/index.md)). To set the recorded time, use the `GIT_AUTHOR_DATE` and `GIT_COMMITTER_DATE` environment variables.
When `commit.gpgsign` is true (or `commit.gpgSign`), `grit commit` signs the new commit object the same way Git does: OpenPGP and X.509 via your configured `gpg`/`gpgsm` program, or SSH via `ssh-keygen -Y sign` when `gpg.format` is `ssh`. Signing uses `user.signingkey` and the same `gpg.*` settings Git reads. [`grit merge`](https://grit-scm.com/docs/merge/index.md) and [`grit pick`](https://grit-scm.com/docs/pick/index.md) honor the same policy when they create commits.
`grit commit` fails when there's nothing to commit, when HEAD is detached rather than on a branch, and when the index still has **unmerged** paths (for example after a merge conflict). Resolve conflicts, stage the result with [`grit add`](https://grit-scm.com/docs/add/index.md), then commit again.
When a merge is in progress (`MERGE_HEAD` is present) and every conflict is resolved in the index, `grit commit` records a **merge commit** with two parents (your branch tip and the merged tip) and clears merge state the same way Git does after `git commit`.
## Options
| Option | Description |
| --- | --- |
| `<message>` | The commit message. |
| `-m`, `--message <message>` | The commit message, as an option. Use either this or the argument, not both. |
| `-a`, `--all` | Stage every change first. This is always what `grit commit` does; the option is accepted so that `git` habits like `-am` keep working. |
## Examples
Commit everything:
```console
$ grit commit "Add the greeting"
[main 217c6f9] Add the greeting
2 changes committed
```
The same, written the way you'd write it for `git`:
```console
$ grit commit -am "Add the greeting"
```
A longer message with a body:
```console
$ grit commit -m "Add the greeting
Prints hi on startup so we know the binary runs."
```
## JSON output
Pass `--json` for stable, scripting-friendly output:
| Field | Type | Meaning |
| ----- | ---- | ------- |
| `oid` | string | Full commit object id (40 hex chars for SHA-1) |
| `branch` | string | Short branch name (e.g. `main`) |
| `subject` | string | First line of the commit message |
| `changes` | number | Path changes vs the parent commit tree |
Example:
```json
{
"oid": "92501f188ae0815af09a0cef6e121eddda4113cf",
"branch": "main",
"subject": "second",
"changes": 1
}
```
## See also
[grit add](https://grit-scm.com/docs/add/index.md), [grit status](https://grit-scm.com/docs/status/index.md), [grit log](https://grit-scm.com/docs/log/index.md), [grit config](https://grit-scm.com/docs/config/index.md)
# https://grit-scm.com/docs/diff/index.md
# grit diff
> Show uncommitted changes, or the change a commit introduced.
## Synopsis
```text
grit diff [<commit>]
```
## Description
With no argument, shows every uncommitted change: the working tree, staged or not, compared with the last commit. With a commit, shows the change that commit introduced, compared with its first parent.
Each file starts with its path, and each hunk with its position. Lines have two number columns, the line number before and after the change. In a terminal, removed lines are red, added lines are green, and the words that changed within a line are highlighted. When the output isn't a terminal, or `NO_COLOR` is set, lines are marked with `-` and `+` instead. Three lines of unchanged context are shown around each change. Binary files are reported but not shown.
`<commit>` can be anything that names a commit: a full or short commit id, a branch or tag name, or an expression like `HEAD~2`.
## Options
| Option | Description |
| --- | --- |
| `<commit>` | The commit whose change to show. Omit to show uncommitted changes. |
## Examples
What have I changed since the last commit?
```console
$ grit diff
main.rs
@@ -1 +1 @@
1 │ - fn main() {}
1 │ + fn main() {
2 │ + println!("hi");
3 │ + }
```
What did the commit before the last one change?
```console
$ grit diff HEAD~1
```
List the files changed by a commit:
```console
$ grit diff v0.1 --json --filter '.files[].path'
[
"README.md",
"main.rs"
]
```
## JSON output
Pass `--json` for stable, scripting-friendly output:
| Field | Type | Meaning |
| ----- | ---- | ------- |
| `files` | array | Changed files, each with `path`, `status`, `binary`, and `hunks`. |
Nested fields include `files[].status` (`added`, `modified`, `deleted`, and so on), `hunks[].lines[].kind` (`context`, `add`, or `del`), line numbers on `old` and `new`, and `segments` with optional `emphasis` on intra-line changes.
Example:
```json
{
"files": [
{
"path": "main.rs",
"status": "modified",
"binary": false,
"hunks": [
{
"old_start": 1,
"new_start": 1,
"lines": [
{
"kind": "del",
"old": 1,
"segments": [
{ "text": "fn main() ", "emphasis": false },
{ "text": "{}", "emphasis": true }
]
},
{
"kind": "add",
"new": 1,
"segments": [
{ "text": "fn main() ", "emphasis": false },
{ "text": "{", "emphasis": true }
]
}
]
}
]
}
]
}
```
## Markdown output
Pass [`--markdown`](https://grit-scm.com/docs/global-options/index.md) for one `diff`-fenced unified patch per changed file:
```text
File: main.rs
@@ -1,1 +1,2 @@
fn main() {
+ println!("hello");
}
```
Each changed file is introduced with a level-2 heading on stdout, followed by a `diff`-fenced patch.
## See also
[grit status](https://grit-scm.com/docs/status/index.md), [grit show](https://grit-scm.com/docs/show/index.md), [grit log](https://grit-scm.com/docs/log/index.md)
# https://grit-scm.com/docs/restore/index.md
# grit restore
> Restore working tree and/or index paths from HEAD, the index, or another revision.
## Synopsis
```text
grit restore [--staged] [--worktree] [--source=<rev>] -- <path>…
```
## Description
Discards local changes for tracked paths you name. By default, `grit restore` resets the **working tree** to match the **index** (the same idea as unstaging worktree edits while keeping the index as-is).
- `--staged` resets the **index** from `HEAD` (or from `--source` when you pass it). On an unborn branch, staged paths are removed from the index.
- `--worktree` resets the **working tree**. When you omit both flags, only the worktree is restored.
- `--source=<rev>` reads content from a commit or tree instead of the usual default (`HEAD` for `--staged`, the index for the worktree).
- Paths that are missing in the source are removed from the target. Untracked files are never touched.
## Options
| Option | Description |
| --- | --- |
| `<path>…` | One or more pathspecs (required). |
| `-S`, `--staged` | Restore the index. |
| `-W`, `--worktree` | Restore the working tree. |
| `--source` | Commit or tree to restore from. |
## Examples
Discard unstaged edits to a file (worktree ← index):
```console
$ grit restore README.md
Restored README.md
```
Unstage a file (index ← HEAD):
```console
$ grit restore --staged README.md
Restored README.md
```
Restore the working tree from the previous commit:
```console
$ grit restore --source=HEAD~1 -- README.md
Restored README.md
```
## JSON output
Pass `--json` for scripting:
| Field | Type | Meaning |
| ----- | ---- | ------- |
| `restored` | array of strings | Paths created or updated. |
| `removed` | array of strings | Paths removed because the source had no entry. |
Example:
```json
{
"restored": ["README.md"],
"removed": []
}
```
## Markdown output
Pass `--markdown` for agent-friendly bullet lists of restored and removed paths.
## See also
[grit add](https://grit-scm.com/docs/add/index.md), [grit status](https://grit-scm.com/docs/status/index.md)
# https://grit-scm.com/docs/log/index.md
# grit log
> Show recent commits, newest first, a page at a time.
## Synopsis
```text
grit log [--before <commit>]
```
## Description
Lists the commits reachable from the current commit, newest first, ten at a time. Each line shows the short commit id, the author, when the commit was made and its subject (the first line of its message). The author is shown by the part of their email address before the `@`, or by name when there's no email.
When there's more history, the last line shows the command for the next page.
## Options
| Option | Description |
| --- | --- |
| `--before <commit>` | Start listing at this commit instead of the current one. Use the commit from the `→ more` line to see the next page. |
## Examples
Show recent history:
```console
$ grit log
b52cca6 ada 2 minutes ago Handle empty input
5fbefea ada 1 hour ago Add a greeting test
...
2efcc2d ada 3 days ago Start the project
→ more: grit log --before=a7e3a5e
```
Show the next page:
```console
$ grit log --before=a7e3a5e
```
Get the subjects of the last ten commits:
```console
$ grit log --json --filter '.commits[].subject'
```
## JSON output
Pass `--json` for stable, scripting-friendly output:
| Field | Type | Meaning |
| ----- | ---- | ------- |
| `commits` | array | Up to ten commits, newest first, each with `oid` and `subject`. |
| `next` | string or null | Full commit id to pass to `--before` for the next page, or `null` when there is no more history. |
Example:
```json
{
"commits": [
{
"oid": "92501f188ae0815af09a0cef6e121eddda4113cf",
"subject": "second"
},
{
"oid": "919c45f33de5e5c0bd05f8ffb089f697f4644976",
"subject": "initial"
}
],
"next": null
}
```
## Markdown output
Pass [`--markdown`](https://grit-scm.com/docs/global-options/index.md) for a bullet list of commits (short oid, subject, author, relative date):
```text
- `b52cca6` Handle empty input (ada, 2 minutes ago)
- `5fbefea` Add a greeting test (ada, 1 hour ago)
More history: run `grit log --before=a7e3a5e`
```
## See also
[grit shortlog](https://grit-scm.com/docs/shortlog/index.md), [grit show](https://grit-scm.com/docs/show/index.md)
# https://grit-scm.com/docs/shortlog/index.md
# grit shortlog
> List the commits on this branch that aren't on the target branch yet.
## Synopsis
```text
grit shortlog
grit sl
```
## Description
Shows the current branch, its target branch, and every commit on the current branch that the target doesn't have, newest first. It's the list of what you would be proposing if you opened a pull request now.
The target branch is found the same way as for [`grit status`](https://grit-scm.com/docs/status/index.md#the-target-branch): the `target.branch` setting, then `origin/master`, `origin/main`, `master` and `main`. Unlike `grit status`, which shows at most ten commits, `grit shortlog` lists all of them.
## Options
`grit shortlog` takes no options beyond the [global ones](https://grit-scm.com/docs/global-options/index.md).
## Examples
```console
$ grit shortlog
On feature
Ahead of origin/main by 2 commits
cf18394 ada 2 hours ago Say hi
9a1c2e0 ada 3 hours ago Add a greeting test
```
Count the commits that aren't on the target yet:
```console
$ grit sl --json --filter .ahead
2
```
## JSON output
Pass `--json` for stable, scripting-friendly output:
| Field | Type | Meaning |
| ----- | ---- | ------- |
| `branch` | string | Current branch name. |
| `target` | string or null | Target branch used for comparison, or `null` when none was found. |
| `ahead` | number | How many commits are on the branch but not on the target. |
| `commits` | array | Those commits, newest first, each with `oid` and `subject`. |
Example:
```json
{
"branch": "feature",
"target": "main",
"ahead": 0,
"commits": []
}
```
## Markdown output
Pass [`--markdown`](https://grit-scm.com/docs/global-options/index.md) for a branch summary and commit bullets:
```text
# Branch `feature`
Ahead of `main` by **2** commits.
- `cf18394` Say hi (ada, 1 hour ago)
- `9a1c2e0` Add a greeting test (ada, 2 hours ago)
```
## See also
[grit status](https://grit-scm.com/docs/status/index.md), [grit log](https://grit-scm.com/docs/log/index.md), [grit config](https://grit-scm.com/docs/config/index.md)
# https://grit-scm.com/docs/show/index.md
# grit show
> Show a commit, tag or branch, and a summary of what it changed.
## Synopsis
```text
grit show [<object>]
```
## Description
Shows a commit's id, author, date and full message, followed by a summary of the files it changed and how many lines were added and removed in each. With no argument, it shows the current commit.
`<object>` can be a commit id (full or short), an expression like `HEAD~2`, a branch or a tag. For a branch or tag, the first line names it. For an annotated tag, the tag's own author, date and message come before the commit it points at.
To see the full change a commit made, use [`grit diff <commit>`](https://grit-scm.com/docs/diff/index.md).
## Options
| Option | Description |
| --- | --- |
| `<object>` | The commit, branch or tag to show. Defaults to the current commit. |
## Examples
Show the latest commit:
```console
$ grit show
branch feature
commit cf18394a62c3f845bd9c44927a5a55e014b2a99d
Author: Ada Lovelace <ada@example.com>
Date: 2026-10-07 10:00:00 +0000
Say hi
main.rs | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
```
Show what a tag points at:
```console
$ grit show v0.1
```
Get the subject of a commit:
```console
$ grit show HEAD~1 --json --filter .commit.subject
"Start the project"
```
## JSON output
Pass `--json` for stable, scripting-friendly output:
| Field | Type | Meaning |
| ----- | ---- | ------- |
| `kind` | string | `commit`, `branch`, `tag`, or `annotated_tag`. |
| `ref_name` | string | Branch or tag name when you named a ref; omitted for a raw commit id. |
| `tag` | object | For an annotated tag: `name`, `tagger`, and `message`. |
| `commit` | object | Commit id, parents, author, committer, subject, and full message. |
| `stat` | object | Change stats with `files`, `files_changed`, `insertions`, and `deletions`. |
Example:
```json
{
"kind": "branch",
"ref_name": "feature",
"commit": {
"oid": "92501f188ae0815af09a0cef6e121eddda4113cf",
"parents": ["919c45f33de5e5c0bd05f8ffb089f697f4644976"],
"author": {
"name": "Ada Lovelace",
"email": "ada@example.com",
"date": "2026-10-07 14:54:02 +0000"
},
"committer": {
"name": "Ada Lovelace",
"email": "ada@example.com",
"date": "2026-10-07 14:54:02 +0000"
},
"subject": "second",
"message": "second"
},
"stat": {
"files": [
{
"path": "README.md",
"status": "modified",
"insertions": 1,
"deletions": 0,
"binary": false
}
],
"files_changed": 1,
"insertions": 1,
"deletions": 0
}
}
```
## Markdown output
Pass [`--markdown`](https://grit-scm.com/docs/global-options/index.md) for headings, commit metadata, message body, and a diffstat table:
```text
# Commit `b52cca6`
**Oid:** `92501f188ae0815af09a0cef6e121eddda4113cf`
**Author:** Ada Lovelace <ada@example.com>
**Date:** 2026-10-07 14:54:02 +0000
Subject line as a level-2 heading, then a "Changes" section with a table:
| File | + | − |
| --- | ---: | ---: |
| `README.md` | 1 | 0 |
1 file changed, 1 insertion(+)
```
## See also
[grit diff](https://grit-scm.com/docs/diff/index.md), [grit log](https://grit-scm.com/docs/log/index.md), [grit tag](https://grit-scm.com/docs/tag/index.md)
# https://grit-scm.com/docs/branch/index.md
# grit branch
> List branches, or create or delete one.
## Synopsis
```text
grit branch
grit branch <name>
grit branch -d <name>
grit branch -D <name>
```
## Description
With no arguments, lists your local branches and marks the current one with `*`.
With a name, creates a branch at the current commit. It doesn't switch to the new branch; use [`grit switch -c`](https://grit-scm.com/docs/switch/index.md) to create a branch and switch to it in one step.
Branch names follow the same rules as `git check-ref-format --branch` (no spaces, `..`, `~`, `.lock`, reserved names like `HEAD`, and other characters Git rejects). Invalid names fail before anything is written under `.git/refs`.
With `-d`, deletes a branch. `grit` refuses if the branch has commits that aren't in the current branch, so you can't lose work by accident; `-D` deletes it anyway. You can't delete the branch you're on.
## Options
| Option | Description |
| --- | --- |
| `<name>` | The branch to create or delete. Omit to list branches. |
| `-d`, `--delete` | Delete the branch. It must be fully merged into the current branch. |
| `-D`, `--force` | Delete the branch even if it isn't merged. |
## Examples
```console
$ grit branch
feature
* main
$ grit branch experiment
Created branch experiment
$ grit branch -d experiment
Deleted branch experiment (was cf18394).
```
Deleting a branch with unmerged work:
```console
$ grit branch -d spike
error: the branch 'spike' is not fully merged.
If you are sure you want to delete it, run 'grit branch -D spike'
$ grit branch -D spike
Deleted branch spike (was a7020c2).
```
## JSON output
Pass `--json` for stable, scripting-friendly output. The object's `action` field says what happened:
| Field | Type | Meaning |
| ----- | ---- | ------- |
| `action` | string | `list`, `create`, or `delete`. |
| `current` | string or null | For `list`, the current branch, or `null` when detached. |
| `branches` | array | For `list`, each branch with `name` and `current`. |
| `name` | string | For `create` or `delete`, the branch name. |
| `oid` | string | For `delete`, full id of the tip before deletion. |
| `short_oid` | string | For `delete`, abbreviated tip id. |
Listing branches:
```json
{
"action": "list",
"current": "main",
"branches": [
{ "name": "feature", "current": false },
{ "name": "main", "current": true }
]
}
```
Creating a branch:
```json
{
"action": "create",
"name": "experiment"
}
```
## See also
[grit switch](https://grit-scm.com/docs/switch/index.md), [grit merge](https://grit-scm.com/docs/merge/index.md)
# https://grit-scm.com/docs/switch/index.md
# grit switch
> Switch to another branch, or create one and switch to it.
## Synopsis
```text
grit switch <branch>
grit switch -c <branch>
```
`grit checkout` and `grit co` do the same thing.
## Description
Switches to a local branch and updates the files in your working tree to match it.
`grit switch` won't run while you have uncommitted changes, staged or not, so that nothing gets carried over to the wrong branch by accident. Commit first. Untracked files stay where they are, unless the other branch has a file at the same path; then `grit` stops rather than overwrite it.
With `-c`, creates the branch at the current commit and switches to it.
## Options
| Option | Description |
| --- | --- |
| `<branch>` | The branch to switch to, or to create with `-c`. |
| `-c`, `--create` | Create the branch first, then switch to it. Fails if the branch already exists. |
## Examples
```console
$ grit switch -c feature
Created and switched to branch feature
$ grit switch main
Switched to branch main
```
With uncommitted changes:
```console
$ grit switch main
error: you have uncommitted changes — commit them before switching
```
## JSON output
Pass `--json` for stable, scripting-friendly output:
| Field | Type | Meaning |
| ----- | ---- | ------- |
| `branch` | string | The branch you switched to. |
| `created` | boolean | `true` when `-c` created the branch; otherwise `false`. |
Example:
```json
{
"branch": "feature",
"created": true
}
```
## See also
[grit branch](https://grit-scm.com/docs/branch/index.md), [grit merge](https://grit-scm.com/docs/merge/index.md), [grit status](https://grit-scm.com/docs/status/index.md)
# https://grit-scm.com/docs/merge/index.md
# grit merge
> Merge another branch into the current one.
## Synopsis
```text
grit merge <branch>
```
## Description
Brings the commits from `<branch>` into the current branch:
- If the current branch already has everything, nothing changes.
- If the current branch has no commits of its own since they diverged, it's moved forward to `<branch>` (a fast-forward). No new commit is made.
- Otherwise both sides are merged and a merge commit is recorded, with the message `Merge <branch>`. When `commit.gpgsign` is enabled, that merge commit is signed like [`grit commit`](https://grit-scm.com/docs/commit/index.md).
`<branch>` can be a local branch or a remote-tracking branch such as `origin/main`. Local branches are looked up first.
If both sides changed the same lines, `grit` lists the conflicting files, exits with an error, and leaves the branch and working tree exactly as they were. `grit` can't resolve conflicts yet; to finish the merge, run `git merge <branch>`, fix the conflicts and commit.
`grit merge` won't run with uncommitted changes, on a branch with no commits, or with a detached HEAD. It also refuses when an untracked file in the working tree would be replaced by a path the merge would check out (same rule as [`grit switch`](https://grit-scm.com/docs/switch/index.md)); the branch and file are left unchanged.
## Options
| Option | Description |
| --- | --- |
| `<branch>` | The branch to merge into the current one. |
## Examples
```console
$ grit merge feature
Fast-forwarded feature → cf18394
$ grit merge origin/main
Merged origin/main into the current branch (acd1d4b)
```
When both branches change the same lines:
```console
$ grit merge topic
error: merge has conflicts in:
README.md
Nothing was changed. grit can't resolve conflicts yet — run `git merge topic` to resolve them.
```
When an untracked file would be overwritten:
```console
$ grit merge feature
error: untracked file 'notes.txt' would be overwritten — move or remove it first
```
## JSON output
Pass `--json` for stable, scripting-friendly output:
| Field | Type | Meaning |
| ----- | ---- | ------- |
| `result` | string | `up_to_date`, `fast_forward`, `merged`, or `set_upstream`. |
| `branch` | string | The branch that was merged in (or set as upstream). |
| `oid` | string or null | Commit the current branch points at after the merge, when applicable. |
| `upstream` | string or null | For `set_upstream`, the remote-tracking branch that was adopted. |
Example:
```json
{
"result": "up_to_date",
"branch": "main"
}
```
## See also
[grit pull](https://grit-scm.com/docs/pull/index.md), [grit pick](https://grit-scm.com/docs/pick/index.md), [grit branch](https://grit-scm.com/docs/branch/index.md)
# https://grit-scm.com/docs/pick/index.md
# grit pick
> Copy a single commit onto the current branch.
## Synopsis
```text
grit pick <commit>
```
## Description
Takes the change `<commit>` made and applies it to the current branch as a new commit (a cherry-pick). The new commit keeps the original author and message. When `commit.gpgsign` is enabled, the new commit is signed like [`grit commit`](https://grit-scm.com/docs/commit/index.md).
`<commit>` can be a full or short commit id, a branch name (to pick the commit at its tip) or an expression like `feature~2`.
`grit pick` works on one commit at a time and keeps it simple. It refuses, and changes nothing, when:
- you have uncommitted changes, or the current branch has no commits, or HEAD is detached
- `<commit>` is a merge commit
- `<commit>` doesn't change anything, or its change is already on the current branch
- the change conflicts with the current branch; the conflicting files are listed
- an untracked file would be replaced by a path the pick would check out (same rule as [`grit switch`](https://grit-scm.com/docs/switch/index.md))
## Options
| Option | Description |
| --- | --- |
| `<commit>` | The commit to copy onto the current branch. |
## Examples
Pick the latest commit from another branch:
```console
$ grit pick feature
Picked cf18394 → 4be20a1 Say hi
```
Pick a commit by id:
```console
$ grit pick 9a1c2e0
```
When an untracked file would be overwritten:
```console
$ grit pick feature
error: untracked file 'notes.txt' would be overwritten — move or remove it first
```
## JSON output
Pass `--json` for stable, scripting-friendly output:
| Field | Type | Meaning |
| ----- | ---- | ------- |
| `source` | string | Full id of the commit that was picked. |
| `oid` | string | Full id of the new commit on the current branch. |
| `subject` | string | Subject line of the picked commit. |
Example:
```json
{
"source": "6e513d5cd6ab8d618238e22d7ca55d942b55964a",
"oid": "6e513d5cd6ab8d618238e22d7ca55d942b55964a",
"subject": "two"
}
```
## See also
[grit merge](https://grit-scm.com/docs/merge/index.md), [grit log](https://grit-scm.com/docs/log/index.md)
# https://grit-scm.com/docs/tag/index.md
# grit tag
> List tags, or create or delete one. A new tag points at the current commit.
## Synopsis
```text
grit tag
grit tag <name>
grit tag -d <name>
```
## Description
With no arguments, lists your tags. With a name, creates a tag pointing at the current commit; tags created by `grit` are lightweight tags, with no message of their own. With `-d`, deletes a tag.
Tag names must be valid as `refs/tags/<name>` under Git's ref-name rules (same checks as `git check-ref-format refs/tags/<name>`). Invalid names are rejected before writing under `.git/refs`.
Tags are local until you publish them with [`grit push --tags`](https://grit-scm.com/docs/push/index.md).
## Options
| Option | Description |
| --- | --- |
| `<name>` | The tag to create or delete. Omit to list tags. |
| `-d`, `--delete` | Delete the tag. |
## Examples
```console
$ grit tag v0.1
Created tag v0.1
$ grit tag
v0.1
$ grit push --tags
pushed --tags → origin refs/tags/v0.1
$ grit tag -d v0.1
Deleted tag v0.1
```
## JSON output
Pass `--json` for stable, scripting-friendly output. The object's `action` field says what happened:
| Field | Type | Meaning |
| ----- | ---- | ------- |
| `action` | string | `list`, `create`, or `delete`. |
| `tags` | array | For `list`, each tag with `name` and `oid`. |
| `name` | string | For `create` or `delete`, the tag name. |
| `oid` | string | For `create`, full id of the commit the tag points at. |
Listing tags:
```json
{
"action": "list",
"tags": [
{
"name": "v0.1",
"oid": "92501f188ae0815af09a0cef6e121eddda4113cf"
}
]
}
```
Creating a tag:
```json
{
"action": "create",
"name": "v0.1",
"oid": "92501f188ae0815af09a0cef6e121eddda4113cf"
}
```
## See also
[grit push](https://grit-scm.com/docs/push/index.md), [grit show](https://grit-scm.com/docs/show/index.md)
# https://grit-scm.com/docs/remote/index.md
# grit remote
> List remotes, add one, or list refs on a remote.
## Synopsis
```text
grit remote
grit remote add <name> <url>
grit remote refs <remote-or-url> [--heads] [--tags] [<prefix>…]
```
## Description
A remote is another copy of the repository that you fetch from and push to, usually on a server. With no arguments, `grit remote` lists your remotes and their URLs.
`grit remote add` adds a remote. [`grit fetch`](https://grit-scm.com/docs/fetch/index.md) then stores the remote's branches as remote-tracking branches named `<name>/<branch>`, such as `origin/main`. [`grit clone`](https://grit-scm.com/docs/clone/index.md) adds a remote called `origin` for you.
`grit remote refs` lists references on a configured remote name or a literal URL/path (same transports as [`grit clone`](https://grit-scm.com/docs/clone/index.md)), matching `git ls-remote` ordering.
## Options
| Option | Description |
| --- | --- |
| `add <name> <url>` | Add a remote called `<name>` at `<url>`. Fails if a remote with that name exists. |
| `refs <remote-or-url>` | List refs on the remote (or URL). |
| `--heads` | With `refs`, only `refs/heads/`. |
| `--tags` | With `refs`, only `refs/tags/`. |
| `<prefix>…` | With `refs`, optional ref prefixes (same rules as `git ls-remote`). |
## Examples
```console
$ grit remote add origin https://github.com/ada/project.git
Added remote origin → https://github.com/ada/project.git
$ grit remote
origin https://github.com/ada/project.git
$ grit remote refs origin
a1b2c3d4e5f6789012345678901234567890abcd refs/heads/main
```
## JSON output
Pass `--json` for stable, scripting-friendly output:
| Field | Type | Meaning |
| ----- | ---- | ------- |
| `action` | string | `list`, `add`, or `refs`. |
| `remotes` | array | For `list`, each remote with `name` and `url`. |
| `name` | string | For `add`, the remote name. |
| `url` | string | For `add`, the remote URL or path. |
| `refs` | array | For `refs`, each entry with `name`, `oid`, optional `peeled`, optional `symref_target`. |
Listing remotes:
```json
{
"action": "list",
"remotes": [
{
"name": "origin",
"url": "https://github.com/ada/project.git"
}
]
}
```
Adding a remote:
```json
{
"action": "add",
"name": "origin",
"url": "https://github.com/ada/project.git"
}
```
Listing refs:
```json
{
"action": "refs",
"refs": [
{
"name": "refs/heads/main",
"oid": "a1b2c3d4e5f6789012345678901234567890abcd",
"peeled": null,
"symref_target": null
}
]
}
```
## Markdown output
Pass `--markdown` for an agent-friendly Markdown table of refs (a “Remote refs” heading, then columns — not JSON). Example shape:
```text
Remote refs
| Ref | Object | Peeled | Symref target |
| --- | --- | --- | --- |
| `refs/heads/main` | `a1b2c3…` | — | — |
| `refs/tags/v1` | `tagoid…` | `commitoid…` | — |
```
## See also
[grit fetch](https://grit-scm.com/docs/fetch/index.md), [grit push](https://grit-scm.com/docs/push/index.md), [grit clone](https://grit-scm.com/docs/clone/index.md)
# https://grit-scm.com/docs/fetch/index.md
# grit fetch
> Download new commits, branches and tags from a remote.
## Synopsis
```text
grit fetch [<remote>]
```
## Description
Downloads everything new from a remote and updates your remote-tracking branches, such as `origin/main`, along with any new tags. Your own branches and working tree are left alone; to bring the new commits into your branch, use [`grit merge`](https://grit-scm.com/docs/merge/index.md) or [`grit pull`](https://grit-scm.com/docs/pull/index.md).
`<remote>` may be a configured remote name or a path to a [git bundle](https://git-scm.com/docs/git-bundle) file (detected by the bundle signature, not the file extension). Bundle fetches verify that prerequisite commits are already in your repository before applying the pack.
Each updated ref is listed with its old and new commit.
Repositories created as shallow clones with Git (for example `git clone --depth 1`) are supported: `grit fetch` respects the existing shallow boundary, does not create tag refs to missing commits, and leaves a clean repository when there is nothing new to download.
## Options
| Option | Description |
| --- | --- |
| `<remote>` | Configured remote name, or a path/URL to a repository or bundle file. Defaults to `origin`. |
## Examples
```console
$ grit fetch
refs/remotes/origin/main a8e620a → b52cca6
Fetched 1 update from origin.
$ grit fetch
Already up to date with origin.
```
Fetch from another remote:
```console
$ grit fetch upstream
```
## JSON output
Pass `--json` for stable, scripting-friendly output:
| Field | Type | Meaning |
| ----- | ---- | ------- |
| `remote` | string | Remote that was fetched. |
| `updates` | array | Ref updates, each with `ref`, `old_oid`, and `new_oid`. |
| `updated` | number | Count of refs that changed. |
`old_oid` is `null` for a ref that is new, and `new_oid` is `null` for one that was removed.
Example:
```json
{
"remote": "origin",
"updates": [],
"updated": 0
}
```
## See also
[grit pull](https://grit-scm.com/docs/pull/index.md), [grit merge](https://grit-scm.com/docs/merge/index.md), [grit remote](https://grit-scm.com/docs/remote/index.md)
# https://grit-scm.com/docs/pull/index.md
# grit pull
> Fetch from the remote and bring the current branch up to date.
## Synopsis
```text
grit pull
```
## Description
Runs [`grit fetch`](https://grit-scm.com/docs/fetch/index.md), then merges the remote's copy of the current branch into it, as [`grit merge`](https://grit-scm.com/docs/merge/index.md) would: a fast-forward when you have no new commits of your own, and a merge commit when both sides do. On a branch with no commits yet, it simply takes the remote's.
The remote is the one in `branch.<name>.remote`, or `origin`. The remote branch is the one in `branch.<name>.merge`, or the branch with the same name as yours.
Like `grit merge`, `grit pull` won't run with uncommitted changes or a detached HEAD, and stops without changing anything if there are conflicts.
## Options
`grit pull` takes no options beyond the [global ones](https://grit-scm.com/docs/global-options/index.md).
## Examples
```console
$ grit pull
Fast-forwarded origin/main → b52cca6
$ grit pull
Merged origin/main into the current branch (acd1d4b)
$ grit pull
Already up to date.
```
## JSON output
The same shape as [`grit merge`](https://grit-scm.com/docs/merge/index.md#json-output). Pass `--json` for stable, scripting-friendly output:
| Field | Type | Meaning |
| ----- | ---- | ------- |
| `result` | string | `up_to_date`, `fast_forward`, `merged`, or `set_upstream`. |
| `branch` | string | Remote branch that was integrated. |
| `oid` | string or null | Commit the current branch points at after the pull, when applicable. |
| `upstream` | string or null | For `set_upstream`, the remote-tracking branch that was adopted. |
Example:
```json
{
"result": "fast_forward",
"branch": "origin/main",
"oid": "b52cca65378cf17309f0b1f917c6dc4fdd9256f2"
}
```
## See also
[grit fetch](https://grit-scm.com/docs/fetch/index.md), [grit merge](https://grit-scm.com/docs/merge/index.md), [grit push](https://grit-scm.com/docs/push/index.md)
# https://grit-scm.com/docs/push/index.md
# grit push
> Publish the current branch, or your tags, to a remote.
## Synopsis
```text
grit push
grit push --tags
```
## Description
Sends the current branch to the remote, creating the branch there if it doesn't exist. There are no arguments and no upstream to set: the branch goes to `origin`, under the same name. To push a branch somewhere else, set `branch.<name>.remote` and `branch.<name>.merge` with [`grit config`](https://grit-scm.com/docs/config/index.md).
`grit push` never overwrites commits on the remote. If the remote branch has commits you don't have, the push is rejected and `grit` exits with an error; run [`grit pull`](https://grit-scm.com/docs/pull/index.md) and push again.
With `--tags`, pushes every local tag to `origin` instead of the current branch.
For GitHub over HTTPS, if a push fails because you aren't signed in, `grit` offers to run [`grit auth`](https://grit-scm.com/docs/auth/index.md) and then tries again.
## Options
| Option | Description |
| --- | --- |
| `-t`, `--tags` | Push all tags instead of the current branch. |
## Examples
```console
$ grit push
pushed main → origin refs/heads/main
$ grit push
origin refs/heads/main already up to date
$ grit push --tags
pushed --tags → origin refs/tags/v0.1
```
When someone else pushed first:
```console
$ grit push
rejected origin refs/heads/main: not a fast-forward — run `grit pull` first
```
## JSON output
Pass `--json` for stable, scripting-friendly output:
| Field | Type | Meaning |
| ----- | ---- | ------- |
| `remote` | string | Remote that was pushed to. |
| `branch` | string | Branch that was pushed, or `--tags`. |
| `results` | array | Per-ref outcomes with `ref` and `status` (`ok`, `up_to_date`, or a rejection). |
| `rejected` | boolean | `true` if any ref was rejected (exit status is also `1`). |
Example:
```json
{
"remote": "origin",
"branch": "main",
"results": [
{ "ref": "refs/heads/main", "status": "ok" }
],
"rejected": false
}
```
## See also
[grit pull](https://grit-scm.com/docs/pull/index.md), [grit tag](https://grit-scm.com/docs/tag/index.md), [grit auth](https://grit-scm.com/docs/auth/index.md)
# https://grit-scm.com/docs/auth/index.md
# grit auth
> Sign in to GitHub so HTTPS pushes and fetches just work.
## Synopsis
```text
grit auth
grit auth logout
```
## Description
Signs you in to GitHub and saves the token, so that [`grit push`](https://grit-scm.com/docs/push/index.md), [`grit fetch`](https://grit-scm.com/docs/fetch/index.md) and [`grit clone`](https://grit-scm.com/docs/clone/index.md) work with private repositories over HTTPS.
`grit auth` uses GitHub's device flow. It prints a web address and a short code. Open `https://github.com/login/device` in your browser, enter the code and approve access. `grit` waits until you do, then saves the token with your credential helper. Every request goes straight to github.com.
A credential helper has to be configured to store the token. On Windows, if none is set, `grit` uses its built-in one ([`grit manager`](https://grit-scm.com/docs/manager/index.md)). Elsewhere, set one with [`grit config`](https://grit-scm.com/docs/config/index.md):
```console
$ grit config --global credential.helper osxkeychain # macOS
$ grit config --global credential.helper libsecret # Linux
$ grit config --global credential.helper store # a plain-text file, any system
```
`grit auth logout` removes the saved GitHub token from your credential helper.
`grit` signs in with its own GitHub OAuth app. To use a different one, set its client id in the `GRIT_GITHUB_CLIENT_ID` environment variable or the `grit.githubClientId` setting.
## Options
| Option | Description |
| --- | --- |
| `logout` | Remove the saved GitHub token. |
## Examples
```console
$ grit auth
To authorize grit, open this page in your browser:
https://github.com/login/device
and enter the code:
1A2B-3C4D
Waiting for you to authorize… (press Ctrl-C to cancel)
✓ Signed in to GitHub — token stored for github.com.
$ grit auth logout
✓ Signed out of GitHub — removed the stored token for github.com.
```
## JSON output
Pass `--json` for stable, scripting-friendly output:
| Field | Type | Meaning |
| ----- | ---- | ------- |
| `authenticated` | boolean | For sign-in, whether a token was stored. |
| `logged_out` | boolean | For `logout`, whether a stored token was removed. |
| `host` | string | GitHub host the credential applies to (usually `github.com`). |
After sign-in:
```json
{
"authenticated": true,
"host": "github.com"
}
```
After logout:
```json
{
"logged_out": true,
"host": "github.com"
}
```
`logged_out` is `false` when no credential helper is configured, since there's nowhere a token could be stored.
## See also
[grit push](https://grit-scm.com/docs/push/index.md), [grit config](https://grit-scm.com/docs/config/index.md), [grit manager](https://grit-scm.com/docs/manager/index.md)
# https://grit-scm.com/docs/bundle/index.md
# grit bundle
> Create, verify, and list git bundle files for offline transfer.
## Synopsis
```text
grit bundle create <file> <rev>…
grit bundle verify <file>
grit bundle list <file>
```
## Description
Git bundles pack refs and objects into a single file. Use them to move history without a network remote, or to seed a clone from removable media.
`create` walks the given revision specs (same rules as [`grit log`](https://grit-scm.com/docs/log/index.md)), writes prerequisite commits the recipient must already have, lists tip refs in the header, and appends a pack stream. Bundles are detected by the `# v2 git bundle` / `# v3 git bundle` signature, not by the `.bundle` file extension alone.
`verify` checks the pack checksum and, when run inside a repository, confirms prerequisite commits are present and connected to your history.
`list` prints the refs recorded in the bundle header.
You can also treat a bundle path like a remote: [`grit fetch`](https://grit-scm.com/docs/fetch/index.md) and [`grit clone`](https://grit-scm.com/docs/clone/index.md) accept a path to a bundle file.
## Options
`create`:
| Argument | Description |
| --- | --- |
| `<file>` | Output bundle path. |
| `<rev>…` | One or more positive revision specs (commits, branches, ranges). |
`verify` / `list`:
| Argument | Description |
| --- | --- |
| `<file>` | Existing bundle file. |
## Examples
```console
$ grit bundle create backup.bundle main
Wrote bundle backup.bundle (1 refs).
$ grit bundle verify backup.bundle
backup.bundle is valid
The bundle uses this hash algorithm: sha1
The bundle contains 1 refs:
f4e623f540cd491f8856e9487a3da5f8242307f0 refs/heads/main
$ grit bundle list backup.bundle
f4e623f540cd491f8856e9487a3da5f8242307f0 refs/heads/main
```
## JSON output
`grit bundle verify --json`:
| Field | Type | Meaning |
| ----- | ---- | ------- |
| `path` | string | Bundle file path. |
| `ok` | boolean | Whether verification succeeded. |
| `hash_algorithm` | string | Object hash used by the pack (`sha1` or `sha256`). |
| `references` | array | Each entry has `name` and `oid`. |
| `prerequisites` | array of strings | Required commit ids (hex). |
| `missing_prerequisites` | array of strings | Prerequisite ids absent from the current repo (empty when not in a repo or when `ok` is true). |
```json
{
"path": "backup.bundle",
"ok": true,
"hash_algorithm": "sha1",
"references": [
{
"name": "refs/heads/main",
"oid": "f4e623f540cd491f8856e9487a3da5f8242307f0"
}
],
"prerequisites": [],
"missing_prerequisites": []
}
```
`grit bundle list --json`:
| Field | Type | Meaning |
| ----- | ---- | ------- |
| `path` | string | Bundle file path. |
| `references` | array | Refs from the bundle header (`name`, `oid`). |
```json
{
"path": "backup.bundle",
"references": [
{
"name": "refs/heads/main",
"oid": "f4e623f540cd491f8856e9487a3da5f8242307f0"
}
]
}
```
`grit bundle create --json`:
| Field | Type | Meaning |
| ----- | ---- | ------- |
| `path` | string | Output bundle path. |
| `refs` | number | Count of refs written to the header. |
## Markdown output
Pass `--markdown` on any `grit bundle` subcommand for the same JSON document wrapped for agents (see [Global options](https://grit-scm.com/docs/global-options/index.md)).
## See also
[grit fetch](https://grit-scm.com/docs/fetch/index.md), [grit clone](https://grit-scm.com/docs/clone/index.md), [grit remote](https://grit-scm.com/docs/remote/index.md)
# https://grit-scm.com/docs/update/index.md
# grit update
> Update grit to the latest release.
## Synopsis
```text
grit update
```
## Description
Downloads the latest release of `grit` and installs it over the copy you're running. It does this by running the same install script as the one-line install on the [Install](https://grit-scm.com/docs/install/index.md) page: `curl -fsSL https://grit-scm.com/install | sh` on macOS and Linux, which needs `sh` and `curl`, and `irm https://grit-scm.com/install.ps1 | iex` in PowerShell on Windows.
The installer prints its own progress. If you installed `grit` with `cargo install`, update it with `cargo install grit-cli` instead.
## Options
`grit update` takes no options beyond the [global ones](https://grit-scm.com/docs/global-options/index.md).
## Examples
```console
$ grit update
Updating grit (current: 0.5.0)
Install directory: /home/ada/.local/bin
...
```
## JSON output
Pass `--json` for stable, scripting-friendly output:
| Field | Type | Meaning |
| ----- | ---- | ------- |
| `updated` | boolean | Whether the install script was started successfully. |
| `version` | string | Version of `grit` that ran the update (not necessarily the version installed). |
Example:
```json
{
"updated": true,
"version": "0.5.0"
}
```
With `--json`, the installer's progress goes to stderr so stdout carries only the JSON object.
## See also
[Docs overview](https://grit-scm.com/docs/index.md)
# https://grit-scm.com/docs/skill/index.md
# grit skill
> Print an agent skill that explains how to use grit.
## Synopsis
```text
grit skill
```
## Description
Prints a `SKILL.md` file for coding agents that explains how to use `grit`: the JSON output contract, the everyday commands, how `grit commit` differs from `git commit`, how to stay non-interactive, and what to do with `git` instead. It uses the [Agent Skills](https://agentskills.io) format, with `name` and `description` front matter, so agents that load skills pick it up when a task involves version control.
The skill is built into the binary and names the version that printed it, so regenerate it after [`grit update`](https://grit-scm.com/docs/update/index.md) to keep it current.
Save it where your agent looks for skills, for example `.agents/skills/grit/SKILL.md` in a project, or `~/.claude/skills/grit/SKILL.md` for Claude Code across all projects.
## Options
`grit skill` takes no options besides the [global options](https://grit-scm.com/docs/global-options/index.md).
## Examples
Install the skill in the current project:
```console
$ mkdir -p .agents/skills/grit
$ grit skill > .agents/skills/grit/SKILL.md
```
Read the start of it:
```console
$ grit skill | head -4
---
name: grit
description: Use the grit CLI for version control in Git repositories — status, diffs, commits, branches, merges, cherry-picks, fetch/pull/push and tags — with JSON output for scripts and agents. Use when a task involves committing, branching, syncing with a remote or reading history and `grit` is installed.
---
```
## JSON output
Pass `--json` to get the skill text along with where to save it:
| Field | Type | Meaning |
| ----- | ---- | ------- |
| `name` | string | The skill's name, `grit`. |
| `version` | string | The grit version that generated the skill. |
| `path` | string | A conventional place to save it, relative to a project root. |
| `content` | string | The full `SKILL.md` text, front matter included. |
Example (with `content` shortened):
```json
{
"name": "grit",
"version": "0.5.2",
"path": ".agents/skills/grit/SKILL.md",
"content": "---\nname: grit\ndescription: Use the grit CLI for version control …"
}
```
## Markdown output
Pass [`--markdown`](https://grit-scm.com/docs/global-options/index.md) to print the full `SKILL.md` text on stdout (same bytes as human mode, suitable for saving or parsing):
```text
---
name: grit
description: Use the grit CLI for version control …
---
```
## See also
[Agent guide](https://grit-scm.com/docs/agents/index.md), [grit update](https://grit-scm.com/docs/update/index.md), [Global options](https://grit-scm.com/docs/global-options/index.md)
# https://grit-scm.com/docs/completions/index.md
# grit completions
> Generate shell completion scripts for bash, zsh, and fish.
## Synopsis
```text
grit completions <shell>
```
## Description
Prints a shell completion script for the `grit` subcommands and flags in the running binary. Redirect stdout to a file your shell loads, or evaluate it in the current session during setup.
Supported shells: `bash`, `elvish`, `fish`, `powershell`, and `zsh` (whatever `clap_complete` exposes for the installed `grit` version).
The script always matches the CLI you built or installed. After [`grit update`](https://grit-scm.com/docs/update/index.md), regenerate completions so new commands and flags appear.
Release archives also ship pre-generated scripts under `completions/` when you install from a tarball.
## Options
| Argument | Meaning |
| -------- | ------- |
| `<shell>` | One of `bash`, `elvish`, `fish`, `powershell`, or `zsh`. |
`grit completions` rejects the global [`--json`](https://grit-scm.com/docs/global-options/index.md) and [`--markdown`](https://grit-scm.com/docs/global-options/index.md) flags; stdout is always the raw completion script.
## Examples
Generate bash completions for the current session:
```console
$ grit completions bash > /tmp/grit.bash
$ source /tmp/grit.bash
```
Install zsh completions for your user (typical layout):
```bash
grit completions zsh > ~/.local/share/zsh/site-functions/_grit
```
Install fish completions:
```bash
mkdir -p ~/.config/fish/completions
grit completions fish > ~/.config/fish/completions/grit.fish
```
## JSON output
There is no JSON form. `--json` and `--markdown` exit with an error; use the human completion script only.
## Markdown output
None. `--markdown` is rejected for the same reason as `--json`.
## See also
[Install grit](https://grit-scm.com/docs/install/index.md), [grit update](https://grit-scm.com/docs/update/index.md), [Global options](https://grit-scm.com/docs/global-options/index.md)
# https://grit-scm.com/docs/upload-pack/index.md
# grit upload-pack
> Serve a fetch or clone of a repository over stdin and stdout.
## Synopsis
```text
grit upload-pack [--stateless-rpc] [--advertise-refs] <directory>
```
## Description
The server side of fetch and clone. It speaks the Git wire protocol on stdin and stdout, so any Git client, `git` or `grit`, can fetch from a repository it serves. You don't normally run it yourself: an SSH server runs it when a client connects, and `grit-http-server` answers smart HTTP requests by calling the same logic in `grit-lib` in-process (no separate `grit` binary next to the server). It doesn't appear in `grit --help`.
`<directory>` is the repository to serve: a bare repository, a working tree, or a path that names one once `.git` is added. Unlike other commands, `grit upload-pack` doesn't search parent directories, so it serves exactly the repository it was given.
It supports Git protocol versions 0, 1 and 2, chosen by the client through the `GIT_PROTOCOL` environment variable. Refs matching `uploadpack.hideRefs` or `transfer.hideRefs` are not shown to clients.
Shallow and deepen requests (`deepen`, `deepen-since`, `deepen-not`, `deepen-relative`, client `shallow` lines) are honored in protocol v0/v1 and in v2 `fetch` (including the `shallow-info` section and sideband-all framing). Partial-clone filters (`filter blob:none`, `blob:limit=<n>`, `tree:<depth>`, and combinations) follow `uploadpack.allowFilter` and `uploadpackfilter.*` policy. Protocol v2 `want-ref` is available when `uploadpack.allowRefInWant` is set. Optional `want` rules follow `uploadpack.allowTipSha1InWant` and `uploadpack.allowReachableSha1InWant`.
## Options
| Option | Description |
| --- | --- |
| `<directory>` | The repository to serve. |
| `--stateless-rpc` | Answer a single request and exit, without advertising refs first. Used for smart HTTP. |
| `--advertise-refs` | Print the ref advertisement and exit. Used for the first request of smart HTTP. Also accepted as `--http-backend-info-refs`. |
## Examples
Clone over SSH from a server that has `grit` but not `git` installed:
```console
$ git clone --upload-pack='grit upload-pack' ssh://example.com/srv/git/project.git
```
Set it for a remote you already have:
```console
$ git config remote.origin.uploadpack 'grit upload-pack'
```
## JSON output
None. `--json` has no effect, since stdout carries the Git protocol.
## See also
[grit receive-pack](https://grit-scm.com/docs/receive-pack/index.md), [grit clone](https://grit-scm.com/docs/clone/index.md), [grit fetch](https://grit-scm.com/docs/fetch/index.md)
# https://grit-scm.com/docs/receive-pack/index.md
# grit receive-pack
> Accept a push to a repository over stdin and stdout.
## Synopsis
```text
grit receive-pack [--stateless-rpc] [--advertise-refs] <directory>
```
## Description
The server side of push. It speaks the Git wire protocol on stdin and stdout, receives the objects a client sends, and updates the repository's refs. You don't normally run it yourself: an SSH server runs it when a client pushes, and `grit-http-server` answers smart HTTP requests by calling the same logic in `grit-lib` in-process (no separate `grit` binary next to the server). It doesn't appear in `grit --help`.
`<directory>` is the repository to push to: a bare repository, a working tree, or a path that names one once `.git` is added. It doesn't search parent directories.
Every ref update is checked before it's applied, and the client is told which updates were accepted and why any were refused. These settings in the served repository's config control what's allowed:
| Setting | Effect |
| --- | --- |
| `receive.denyNonFastForwards` | Refuse updates that would discard commits from a branch. |
| `receive.denyDeletes` | Refuse to delete refs. |
| `receive.denyCurrentBranch` | Refuse to update the branch checked out in a non-bare repository. On by default; set it to `ignore` or `warn` to allow it. |
| `receive.hideRefs`, `transfer.hideRefs` | Hide refs from pushing clients and refuse updates to them. |
Pushes that ask for an atomic update are applied all or nothing. Server-side hooks are not supported yet.
## Options
| Option | Description |
| --- | --- |
| `<directory>` | The repository to push to. |
| `--stateless-rpc` | Answer a single request and exit, without advertising refs first. Used for smart HTTP. |
| `--advertise-refs` | Print the ref advertisement and exit. Used for the first request of smart HTTP. Also accepted as `--http-backend-info-refs`. |
## Examples
Push over SSH to a server that has `grit` but not `git` installed:
```console
$ git push --receive-pack='grit receive-pack' origin main
```
Set it for a remote you already have:
```console
$ git config remote.origin.receivepack 'grit receive-pack'
```
## JSON output
None. `--json` has no effect, since stdout carries the Git protocol.
## See also
[grit upload-pack](https://grit-scm.com/docs/upload-pack/index.md), [grit push](https://grit-scm.com/docs/push/index.md)
# https://grit-scm.com/docs/manager/index.md
# grit manager
> A credential helper that stores passwords and tokens in the Windows Credential Manager.
## Synopsis
```text
grit manager (get | store | erase)
```
## Description
A Git credential helper backed by the Windows Credential Manager. You don't run it yourself: Git and `grit` run it when they need a password or token. It speaks Git's [credential helper protocol](https://git-scm.com/docs/gitcredentials), reading the request on stdin and, for `get`, writing the credentials it found on stdout.
[`grit auth`](https://grit-scm.com/docs/auth/index.md) sets `credential.helper` to `grit manager` on Windows when no other helper is configured. To set it up yourself:
```text
> grit config --global credential.helper "grit manager"
```
It works only on Windows. On other systems it exits with an error.
## Options
| Option | Description |
| --- | --- |
| `get` | Look up stored credentials for the request. |
| `store` | Save the credentials in the request. |
| `erase` | Remove the credentials matching the request. |
## Examples
```text
> echo "protocol=https`nhost=github.com`n" | grit manager get
protocol=https
host=github.com
username=x-access-token
password=gho_...
```
## JSON output
None. `grit manager` always speaks the credential helper protocol.
## See also
[grit auth](https://grit-scm.com/docs/auth/index.md), [grit config](https://grit-scm.com/docs/config/index.md)
# https://grit-scm.com/docs/library/index.md
# Library guide
> Use grit-lib from Rust — the same engine that powers the grit CLI.
These pages walk through opening a repository, the object database, refs, the index, diffs, history walks, and network transport using `grit-lib`. Each guide includes a compiled example from `grit-examples` that tests against the system `git` binary.
| Page | Topic |
| --- | --- |
| [Repository](https://grit-scm.com/docs/library/repository/index.md) | Discover, open, config, errors |
| [Embedding](https://grit-scm.com/docs/library/embedding/index.md) | Environment, sinks, subprocess injection, concurrency |
| [Objects](https://grit-scm.com/docs/library/objects/index.md) | Odb read/write, object kinds |
| [Refs](https://grit-scm.com/docs/library/refs/index.md) | Resolve, list, update refs and reflog |
| [Index](https://grit-scm.com/docs/library/staging/index.md) | Read index, stage paths, write trees |
| [Diff](https://grit-scm.com/docs/library/diff/index.md) | Tree, index, and blob diffs |
| [Revwalk](https://grit-scm.com/docs/library/revwalk/index.md) | Rev-parse, rev-list, ranges, merge base |
| [Network](https://grit-scm.com/docs/library/network/index.md) | ls-remote, fetch, push, credentials |
| [API map](https://grit-scm.com/docs/library/api-map/index.md) | Generated module and type index with docs.rs links |
For exhaustive API detail see [grit-lib on docs.rs](https://docs.rs/grit-lib).
# https://grit-scm.com/docs/library/api-map/index.md
# grit-lib API map
> Generated index of public grit-lib modules and key types with docs.rs links.
This page is regenerated from the local `grit-lib` rustdoc build (`cargo doc -p grit-lib --no-deps`) whenever you run `make docs`. Each row links to [docs.rs](https://docs.rs/grit-lib/latest/grit_lib/) for the matching item.
| Item | Kind | Summary | docs.rs |
| --- | --- | --- | --- |
| `grit_lib::apply` | module | Unified/git-diff patch parsing for grit apply. | [API](https://docs.rs/grit-lib/latest/grit_lib/apply/index.html) |
| `grit_lib::apply::BinaryPatchPayload` | struct | Binary patch payload as compressed base85 chunks for forward/reverse apply. | [API](https://docs.rs/grit-lib/latest/grit_lib/apply/struct.BinaryPatchPayload.html) |
| `grit_lib::apply::FilePatch` | struct | Represents one file in a unified diff. | [API](https://docs.rs/grit-lib/latest/grit_lib/apply/struct.FilePatch.html) |
| `grit_lib::apply::Hunk` | struct | A single hunk in a unified diff. | [API](https://docs.rs/grit-lib/latest/grit_lib/apply/struct.Hunk.html) |
| `grit_lib::apply::HunkLine` | enum | Inflate zlib-compressed binary payload. | [API](https://docs.rs/grit-lib/latest/grit_lib/apply/enum.HunkLine.html) |
| `grit_lib::attributes` | module | Gitattributes parsing and pattern matching for check-attr and validation. | [API](https://docs.rs/grit-lib/latest/grit_lib/attributes/index.html) |
| `grit_lib::attributes::AttrRule` | struct | One line in a gitattributes file. | [API](https://docs.rs/grit-lib/latest/grit_lib/attributes/struct.AttrRule.html) |
| `grit_lib::attributes::AttrValue` | enum | Parsed attribute value for display (check-attr output). | [API](https://docs.rs/grit-lib/latest/grit_lib/attributes/enum.AttrValue.html) |
| `grit_lib::attributes::MacroTable` | struct | Macro definitions from [attr]name ... | [API](https://docs.rs/grit-lib/latest/grit_lib/attributes/struct.MacroTable.html) |
| `grit_lib::attributes::ParsedGitAttributes` | struct | Result of parsing a gitattributes file. | [API](https://docs.rs/grit-lib/latest/grit_lib/attributes/struct.ParsedGitAttributes.html) |
| `grit_lib::bitmap_walk` | module | Reachability queries using pack / MIDX commit bitmaps (Git prepare_bitmap_walk semantics). | [API](https://docs.rs/grit-lib/latest/grit_lib/bitmap_walk/index.html) |
| `grit_lib::bitmap_walk::BitmapWalkError` | enum | Errors during a bitmap reachability walk. | [API](https://docs.rs/grit-lib/latest/grit_lib/bitmap_walk/enum.BitmapWalkError.html) |
| `grit_lib::bitmap_walk::BitmapWalkUnsupported` | struct | Bitmap walk could not run (unsupported filter or shallow repo); use a non-bitmap walk instead. | [API](https://docs.rs/grit-lib/latest/grit_lib/bitmap_walk/struct.BitmapWalkUnsupported.html) |
| `grit_lib::bitmap_walk::ReachabilityQuery` | struct | Query parameters for a bitmap reachability walk. | [API](https://docs.rs/grit-lib/latest/grit_lib/bitmap_walk/struct.ReachabilityQuery.html) |
| `grit_lib::bitmap_walk::ReachableSet` | struct | Reachable objects from a ReachabilityQuery: in-index bits plus out-of-namespace oids. | [API](https://docs.rs/grit-lib/latest/grit_lib/bitmap_walk/struct.ReachableSet.html) |
| `grit_lib::blame` | module | Blame line-mapping algorithm. | [API](https://docs.rs/grit-lib/latest/grit_lib/blame/index.html) |
| `grit_lib::blame::BlameLine` | struct | A single line attribution. | [API](https://docs.rs/grit-lib/latest/grit_lib/blame/struct.BlameLine.html) |
| `grit_lib::blame::BlameTextconvContext` | struct | annotate-tests.sh “blame huge graft”: octopus graft with 29 parents on commit 00 and a two-line 0/0 file. | [API](https://docs.rs/grit-lib/latest/grit_lib/blame/struct.BlameTextconvContext.html) |
| `grit_lib::bloom` | module | Changed-path Bloom filters for commit-graph files (Git bloom.c compatible). | [API](https://docs.rs/grit-lib/latest/grit_lib/bloom/index.html) |
| `grit_lib::bloom::BloomBuildOutcome` | enum | Result of building a Bloom filter payload for one commit. | [API](https://docs.rs/grit-lib/latest/grit_lib/bloom/enum.BloomBuildOutcome.html) |
| `grit_lib::bloom::BloomFilterInvalid` | struct | Invalid or missing Bloom filter data (zero-length filter, etc.). | [API](https://docs.rs/grit-lib/latest/grit_lib/bloom/struct.BloomFilterInvalid.html) |
| `grit_lib::bloom::BloomFilterSettings` | struct | Settings stored in the BDAT chunk header and used for hashing. | [API](https://docs.rs/grit-lib/latest/grit_lib/bloom/struct.BloomFilterSettings.html) |
| `grit_lib::branch_tracking` | module | Branch vs remote-tracking comparison for status, checkout, and commit (matches git/remote.c). | [API](https://docs.rs/grit-lib/latest/grit_lib/branch_tracking/index.html) |
| `grit_lib::branch_tracking::AheadBehindMode` | enum | How to compare local HEAD to a remote-tracking ref (AHEAD_BEHIND_FULL vs QUICK). | [API](https://docs.rs/grit-lib/latest/grit_lib/branch_tracking/enum.AheadBehindMode.html) |
| `grit_lib::branch_tracking::TrackingStat` | enum | Outcome of comparing refs/heads/<branch> to a tracking ref. | [API](https://docs.rs/grit-lib/latest/grit_lib/branch_tracking/enum.TrackingStat.html) |
| `grit_lib::bundle` | module | Git bundle format (gitformat-bundle). | [API](https://docs.rs/grit-lib/latest/grit_lib/bundle/index.html) |
| `grit_lib::bundle::Bundle` | struct | An opened bundle file on disk. | [API](https://docs.rs/grit-lib/latest/grit_lib/bundle/struct.Bundle.html) |
| `grit_lib::bundle::BundleError` | enum | Bundle read/write/verify failures. | [API](https://docs.rs/grit-lib/latest/grit_lib/bundle/enum.BundleError.html) |
| `grit_lib::bundle::BundleHeader` | struct | Parsed bundle header (everything before the PACK stream). | [API](https://docs.rs/grit-lib/latest/grit_lib/bundle/struct.BundleHeader.html) |
| `grit_lib::bundle::BundleSpec` | struct | Input for write_bundle. | [API](https://docs.rs/grit-lib/latest/grit_lib/bundle/struct.BundleSpec.html) |
| `grit_lib::bundle::BundleVerifyReport` | struct | Outcome of Bundle::verify. | [API](https://docs.rs/grit-lib/latest/grit_lib/bundle/struct.BundleVerifyReport.html) |
| `grit_lib::bundle::BundleVersion` | enum | Supported on-disk bundle header versions. | [API](https://docs.rs/grit-lib/latest/grit_lib/bundle/enum.BundleVersion.html) |
| `grit_lib::bundle::BundleWriter` | struct | Incremental writer for bundle bytes (header + pack). | [API](https://docs.rs/grit-lib/latest/grit_lib/bundle/struct.BundleWriter.html) |
| `grit_lib::bundle::FilterSpec` | struct | Wire filter specification carried in v3 @filter= capabilities. | [API](https://docs.rs/grit-lib/latest/grit_lib/bundle/struct.FilterSpec.html) |
| `grit_lib::bundle::UnbundledRef` | struct | A single ref entry returned from Bundle::unbundle. | [API](https://docs.rs/grit-lib/latest/grit_lib/bundle/struct.UnbundledRef.html) |
| `grit_lib::bundle_remote` | module | Fetch and remote helpers for on-disk bundle files (clone / grit fetch from a .bundle). | [API](https://docs.rs/grit-lib/latest/grit_lib/bundle_remote/index.html) |
| `grit_lib::check_ref_format` | module | Ref-name validation — git check-ref-format rules. | [API](https://docs.rs/grit-lib/latest/grit_lib/check_ref_format/index.html) |
| `grit_lib::check_ref_format::RefNameError` | enum | Errors returned by check_refname_format. | [API](https://docs.rs/grit-lib/latest/grit_lib/check_ref_format/enum.RefNameError.html) |
| `grit_lib::check_ref_format::RefNameOptions` | struct | Options controlling validation. | [API](https://docs.rs/grit-lib/latest/grit_lib/check_ref_format/struct.RefNameOptions.html) |
| `grit_lib::clone` | module | Clone a remote repository: initialize, configure origin, fetch, and set up the default branch. | [API](https://docs.rs/grit-lib/latest/grit_lib/clone/index.html) |
| `grit_lib::clone::CloneError` | enum | Errors during clone. | [API](https://docs.rs/grit-lib/latest/grit_lib/clone/enum.CloneError.html) |
| `grit_lib::clone::CloneOptions` | struct | Options for clone. | [API](https://docs.rs/grit-lib/latest/grit_lib/clone/struct.CloneOptions.html) |
| `grit_lib::clone::CloneOutcome` | struct | Result of a successful clone before working-tree checkout. | [API](https://docs.rs/grit-lib/latest/grit_lib/clone/struct.CloneOutcome.html) |
| `grit_lib::combined_diff_patch` | module | Git-style combined merge diff hunks (diff --cc / diff --combined). | [API](https://docs.rs/grit-lib/latest/grit_lib/combined_diff_patch/index.html) |
| `grit_lib::combined_diff_patch::CombinedDiffWsOptions` | struct | Whitespace handling for combined diffs (Git xdl_opts subset). | [API](https://docs.rs/grit-lib/latest/grit_lib/combined_diff_patch/struct.CombinedDiffWsOptions.html) |
| `grit_lib::combined_tree_diff` | module | Multi-parent combined tree diff (Git diff_tree_paths / find_paths_multitree). | [API](https://docs.rs/grit-lib/latest/grit_lib/combined_tree_diff/index.html) |
| `grit_lib::combined_tree_diff::CombinedDiffPath` | struct | One path in a combined diff: merge result tree vs each parent tree. | [API](https://docs.rs/grit-lib/latest/grit_lib/combined_tree_diff/struct.CombinedDiffPath.html) |
| `grit_lib::combined_tree_diff::CombinedParentSide` | struct | One parent’s contribution at a combined-diff path. | [API](https://docs.rs/grit-lib/latest/grit_lib/combined_tree_diff/struct.CombinedParentSide.html) |
| `grit_lib::combined_tree_diff::CombinedParentStatus` | enum | Per-parent coarse status in a combined diff (A / M / D). | [API](https://docs.rs/grit-lib/latest/grit_lib/combined_tree_diff/enum.CombinedParentStatus.html) |
| `grit_lib::combined_tree_diff::CombinedTreeDiffOptions` | struct | Options for the multitree walk. | [API](https://docs.rs/grit-lib/latest/grit_lib/combined_tree_diff/struct.CombinedTreeDiffOptions.html) |
| `grit_lib::command_runner` | module | Injectable subprocess execution for hooks, filters, credentials, and helpers. | [API](https://docs.rs/grit-lib/latest/grit_lib/command_runner/index.html) |
| `grit_lib::command_runner::CommandEnvironment` | struct | How a child process should inherit or receive environment variables. | [API](https://docs.rs/grit-lib/latest/grit_lib/command_runner/struct.CommandEnvironment.html) |
| `grit_lib::command_runner::CommandExit` | struct | Exit status of a completed child. | [API](https://docs.rs/grit-lib/latest/grit_lib/command_runner/struct.CommandExit.html) |
| `grit_lib::command_runner::CommandHandleError` | struct | Returned when an operation requires a live OS child but the handle is synthetic. | [API](https://docs.rs/grit-lib/latest/grit_lib/command_runner/struct.CommandHandleError.html) |
| `grit_lib::command_runner::CommandOutput` | struct | Output from RunningCommand::wait_with_output. | [API](https://docs.rs/grit-lib/latest/grit_lib/command_runner/struct.CommandOutput.html) |
| `grit_lib::command_runner::CommandRunner` | trait | Spawns subprocesses; the only production implementation uses std::process::Command. | [API](https://docs.rs/grit-lib/latest/grit_lib/command_runner/trait.CommandRunner.html) |
| `grit_lib::command_runner::CommandSpec` | struct | Typed description of a subprocess to spawn. | [API](https://docs.rs/grit-lib/latest/grit_lib/command_runner/struct.CommandSpec.html) |
| `grit_lib::command_runner::CommandStdin` | enum | Stdin source for the child. | [API](https://docs.rs/grit-lib/latest/grit_lib/command_runner/enum.CommandStdin.html) |
| `grit_lib::command_runner::CommandStdio` | enum | Stdio disposition for a child stream. | [API](https://docs.rs/grit-lib/latest/grit_lib/command_runner/enum.CommandStdio.html) |
| `grit_lib::command_runner::RecordedResponse` | enum | Scripted responses for RecordingRunner. | [API](https://docs.rs/grit-lib/latest/grit_lib/command_runner/enum.RecordedResponse.html) |
| `grit_lib::command_runner::RecordingRunner` | struct | Records CommandSpec invocations and returns configurable exit statuses. | [API](https://docs.rs/grit-lib/latest/grit_lib/command_runner/struct.RecordingRunner.html) |
| `grit_lib::command_runner::RunningCommand` | struct | Live child process with optional piped stdio. | [API](https://docs.rs/grit-lib/latest/grit_lib/command_runner/struct.RunningCommand.html) |
| `grit_lib::command_runner::ShellInvocation` | enum | Shell invocation mode (Git sh -c hooks and filters). | [API](https://docs.rs/grit-lib/latest/grit_lib/command_runner/enum.ShellInvocation.html) |
| `grit_lib::command_runner::SystemCommandRunner` | struct | Runs commands with the real OS process API. | [API](https://docs.rs/grit-lib/latest/grit_lib/command_runner/struct.SystemCommandRunner.html) |
| `grit_lib::commit` | module | Commit-metadata helpers shared by the porcelain commands. | [API](https://docs.rs/grit-lib/latest/grit_lib/commit/index.html) |
| `grit_lib::commit_encoding` | module | Git commit encoding labels (encoding header, i18n.commitEncoding) mapped to codecs. | [API](https://docs.rs/grit-lib/latest/grit_lib/commit_encoding/index.html) |
| `grit_lib::commit_graph_file` | module | Parsing Git commit-graph files and Bloom filter lookup (commit-graph.c / bloom.c compatible). | [API](https://docs.rs/grit-lib/latest/grit_lib/commit_graph_file/index.html) |
| `grit_lib::commit_graph_file::BloomWalkStats` | struct | Counters for GIT_TRACE2_PERF Bloom statistics (revision.c trace2_bloom_filter_statistics_atexit). | [API](https://docs.rs/grit-lib/latest/grit_lib/commit_graph_file/struct.BloomWalkStats.html) |
| `grit_lib::commit_graph_file::CommitGraphChain` | struct | Loaded commit-graph chain (newest layer first, matching commit-graph-chain file order). | [API](https://docs.rs/grit-lib/latest/grit_lib/commit_graph_file/struct.CommitGraphChain.html) |
| `grit_lib::commit_graph_file::CommitGraphLayer` | struct | One layer from .git/objects/info/commit-graph or commit-graphs/<hash>.graph. | [API](https://docs.rs/grit-lib/latest/grit_lib/commit_graph_file/struct.CommitGraphLayer.html) |
| `grit_lib::commit_graph_file::ParsedGraphDump` | struct | Result of consulting Bloom filters before running a tree diff (matches revision.c). | [API](https://docs.rs/grit-lib/latest/grit_lib/commit_graph_file/struct.ParsedGraphDump.html) |
| `grit_lib::commit_graph_write` | module | Serialize Git commit-graph v1 files with GDA2 + optional Bloom chunks (commit-graph.c compatible). | [API](https://docs.rs/grit-lib/latest/grit_lib/commit_graph_write/index.html) |
| `grit_lib::commit_graph_write::BloomWriteStats` | struct | Counters emitted as GIT_TRACE2_EVENT for Bloom generation (commit-graph.c). | [API](https://docs.rs/grit-lib/latest/grit_lib/commit_graph_write/struct.BloomWriteStats.html) |
| `grit_lib::commit_graph_write::CommitGraphCommitInfo` | struct | Per-commit data needed to write CDAT / Bloom. | [API](https://docs.rs/grit-lib/latest/grit_lib/commit_graph_write/struct.CommitGraphCommitInfo.html) |
| `grit_lib::commit_pretty` | module | Human-oriented commit one-line formats shared by porcelain commands. | [API](https://docs.rs/grit-lib/latest/grit_lib/commit_pretty/index.html) |
| `grit_lib::commit_trailers` | module | Cherry-pick / sign-off trailer handling compatible with Git’s sequencer.c and trailer.c. | [API](https://docs.rs/grit-lib/latest/grit_lib/commit_trailers/index.html) |
| `grit_lib::commit_trailers::TrailerOpts` | struct | Options parsed from a %(trailers:...) pretty placeholder, mirroring Git’s process_trailer_options in pretty.c / trailer.c. | [API](https://docs.rs/grit-lib/latest/grit_lib/commit_trailers/struct.TrailerOpts.html) |
| `grit_lib::config` | module | Git-compatible configuration file parser and accessor. | [API](https://docs.rs/grit-lib/latest/grit_lib/config/index.html) |
| `grit_lib::config::ConfigEntry` | struct | A single configuration entry with its origin metadata. | [API](https://docs.rs/grit-lib/latest/grit_lib/config/struct.ConfigEntry.html) |
| `grit_lib::config::ConfigFile` | struct | A parsed configuration file that preserves the raw text for round-trip editing (set/unset/rename-section/remove-section). | [API](https://docs.rs/grit-lib/latest/grit_lib/config/struct.ConfigFile.html) |
| `grit_lib::config::ConfigIncludeOrigin` | enum | Where a ConfigFile was loaded from for Git include semantics. | [API](https://docs.rs/grit-lib/latest/grit_lib/config/enum.ConfigIncludeOrigin.html) |
| `grit_lib::config::ConfigScope` | enum | The scope (origin) of a configuration value. | [API](https://docs.rs/grit-lib/latest/grit_lib/config/enum.ConfigScope.html) |
| `grit_lib::config::ConfigSet` | struct | A merged view across all configuration scopes. | [API](https://docs.rs/grit-lib/latest/grit_lib/config/struct.ConfigSet.html) |
| `grit_lib::config::GitConfigIntStrictError` | enum | Why parse_git_config_int_strict failed (mirrors Git errno after git_parse_signed). | [API](https://docs.rs/grit-lib/latest/grit_lib/config/enum.GitConfigIntStrictError.html) |
| `grit_lib::config::IncludeContext` | struct | Context for evaluating [includeIf] conditions (gitdir:, onbranch:, hasconfig:). | [API](https://docs.rs/grit-lib/latest/grit_lib/config/struct.IncludeContext.html) |
| `grit_lib::config::LoadConfigOptions` | struct | Options controlling how ConfigSet::load_with_options merges files and includes. | [API](https://docs.rs/grit-lib/latest/grit_lib/config/struct.LoadConfigOptions.html) |
| `grit_lib::configuration` | module | Configuration and identity: config cascade, .gitmodules, author/committer idents. | [API](https://docs.rs/grit-lib/latest/grit_lib/configuration/index.html) |
| `grit_lib::connectivity` | module | Reachability checks for push / receive-pack connectivity verification. | [API](https://docs.rs/grit-lib/latest/grit_lib/connectivity/index.html) |
| `grit_lib::credentials` | module | Credential layer — Git-compatible credential filling/approval/rejection for library embedders. | [API](https://docs.rs/grit-lib/latest/grit_lib/credentials/index.html) |
| `grit_lib::credentials::Credential` | struct | A structured Git credential. | [API](https://docs.rs/grit-lib/latest/grit_lib/credentials/struct.Credential.html) |
| `grit_lib::credentials::CredentialProvider` | trait | The pluggable credential seam an embedder implements (or wraps). | [API](https://docs.rs/grit-lib/latest/grit_lib/credentials/trait.CredentialProvider.html) |
| `grit_lib::credentials::HelperCredentialProvider` | struct | Git-compatible CredentialProvider that runs the configured credential.helper programs. | [API](https://docs.rs/grit-lib/latest/grit_lib/credentials/struct.HelperCredentialProvider.html) |
| `grit_lib::crlf` | module | CRLF / EOL conversion and clean/smudge filter support. | [API](https://docs.rs/grit-lib/latest/grit_lib/crlf/index.html) |
| `grit_lib::crlf::AttrRule` | struct | A parsed .gitattributes rule. | [API](https://docs.rs/grit-lib/latest/grit_lib/crlf/struct.AttrRule.html) |
| `grit_lib::crlf::AutoCrlf` | enum | What core.autocrlf is set to. | [API](https://docs.rs/grit-lib/latest/grit_lib/crlf/enum.AutoCrlf.html) |
| `grit_lib::crlf::ConversionConfig` | struct | Global conversion settings derived from config. | [API](https://docs.rs/grit-lib/latest/grit_lib/crlf/struct.ConversionConfig.html) |
| `grit_lib::crlf::ConversionError` | enum | Error from internal encoding helpers (not public convert_to_git surface). | [API](https://docs.rs/grit-lib/latest/grit_lib/crlf/enum.ConversionError.html) |
| `grit_lib::crlf::ConvertToGitOpts` | struct | Optional inputs for convert_to_git_with_opts (Git CONV_EOL_RENORMALIZE / index blob). | [API](https://docs.rs/grit-lib/latest/grit_lib/crlf/struct.ConvertToGitOpts.html) |
| `grit_lib::crlf::CoreEol` | enum | What core.eol is set to. | [API](https://docs.rs/grit-lib/latest/grit_lib/crlf/enum.CoreEol.html) |
| `grit_lib::crlf::CrlfLegacyAttr` | enum | Legacy crlf gitattribute (deprecated in Git; still honored for EOL conversion). | [API](https://docs.rs/grit-lib/latest/grit_lib/crlf/enum.CrlfLegacyAttr.html) |
| `grit_lib::crlf::DiffAttr` | enum | How the diff gitattribute affects diff output. | [API](https://docs.rs/grit-lib/latest/grit_lib/crlf/enum.DiffAttr.html) |
| `grit_lib::crlf::EolAttr` | enum | Per-file eol attribute from .gitattributes. | [API](https://docs.rs/grit-lib/latest/grit_lib/crlf/enum.EolAttr.html) |
| `grit_lib::crlf::FileAttrs` | struct | Per-file attributes relevant to conversion. | [API](https://docs.rs/grit-lib/latest/grit_lib/crlf/struct.FileAttrs.html) |
| `grit_lib::crlf::MergeAttr` | enum | Per-file merge attribute from .gitattributes. | [API](https://docs.rs/grit-lib/latest/grit_lib/crlf/enum.MergeAttr.html) |
| `grit_lib::crlf::SafeCrlf` | enum | What core.safecrlf is set to. | [API](https://docs.rs/grit-lib/latest/grit_lib/crlf/enum.SafeCrlf.html) |
| `grit_lib::crlf::TextAttr` | enum | Per-file text attribute from .gitattributes. | [API](https://docs.rs/grit-lib/latest/grit_lib/crlf/enum.TextAttr.html) |
| `grit_lib::crlf::WorkTreeEncodingError` | enum | Working-tree encoding conversion failure (Git reencode_string_len returning NULL). | [API](https://docs.rs/grit-lib/latest/grit_lib/crlf/enum.WorkTreeEncodingError.html) |
| `grit_lib::delta_encode` | module | Encode Git pack binary deltas (format decoded by crate::unpack_objects::apply_delta). | [API](https://docs.rs/grit-lib/latest/grit_lib/delta_encode/index.html) |
| `grit_lib::delta_encode::DeltaIndex` | struct | Rolling-hash index over a base buffer for reuse when encoding many targets. | [API](https://docs.rs/grit-lib/latest/grit_lib/delta_encode/struct.DeltaIndex.html) |
| `grit_lib::delta_islands` | module | Delta islands — restrict cross-island deltas in pack-objects (--delta-islands). | [API](https://docs.rs/grit-lib/latest/grit_lib/delta_islands/index.html) |
| `grit_lib::delta_islands::DeltaIslands` | struct | Computed island marks for a pack-objects run. | [API](https://docs.rs/grit-lib/latest/grit_lib/delta_islands/struct.DeltaIslands.html) |
| `grit_lib::delta_islands::IslandBitmap` | struct | One island membership bitmap (one bit per deduplicated island). | [API](https://docs.rs/grit-lib/latest/grit_lib/delta_islands/struct.IslandBitmap.html) |
| `grit_lib::diagnostics` | module | Git-style diagnostic prefixes and typed warning sinks for embedders and the CLI. | [API](https://docs.rs/grit-lib/latest/grit_lib/diagnostics/index.html) |
| `grit_lib::diagnostics::CollectingDiagnostics` | struct | Collects warnings (and traces) for tests and the CLI. | [API](https://docs.rs/grit-lib/latest/grit_lib/diagnostics/struct.CollectingDiagnostics.html) |
| `grit_lib::diagnostics::DiagnosticSink` | trait | Receives warnings and optional trace lines from grit-lib. | [API](https://docs.rs/grit-lib/latest/grit_lib/diagnostics/trait.DiagnosticSink.html) |
| `grit_lib::diagnostics::NullDiagnostics` | struct | Discards all diagnostics (default for crate::repo::Repository). | [API](https://docs.rs/grit-lib/latest/grit_lib/diagnostics/struct.NullDiagnostics.html) |
| `grit_lib::diagnostics::Trace` | enum | Optional trace events (network debugging, etc.), separate from Warning. | [API](https://docs.rs/grit-lib/latest/grit_lib/diagnostics/enum.Trace.html) |
| `grit_lib::diagnostics::Warning` | enum | A non-fatal condition worth surfacing to the user or an embedder. | [API](https://docs.rs/grit-lib/latest/grit_lib/diagnostics/enum.Warning.html) |
| `grit_lib::diff` | module | Diff machinery — compare trees, index entries, and working tree files. | [API](https://docs.rs/grit-lib/latest/grit_lib/diff/index.html) |
| `grit_lib::diff::DiffEntry` | struct | A single diff entry representing one changed path. | [API](https://docs.rs/grit-lib/latest/grit_lib/diff/struct.DiffEntry.html) |
| `grit_lib::diff::DiffIndexToWorktreeOptions` | struct | Additional inputs for diff_index_to_worktree_with_options. | [API](https://docs.rs/grit-lib/latest/grit_lib/diff/struct.DiffIndexToWorktreeOptions.html) |
| `grit_lib::diff::DiffStatus` | enum | The kind of change between two sides of a diff. | [API](https://docs.rs/grit-lib/latest/grit_lib/diff/enum.DiffStatus.html) |
| `grit_lib::diff::SubmodulePorcelainFlags` | struct | Submodule dirty bits aligned with Git’s DIRTY_SUBMODULE_* / porcelain v2 S??? | [API](https://docs.rs/grit-lib/latest/grit_lib/diff/struct.SubmodulePorcelainFlags.html) |
| `grit_lib::diff::WorktreeAddRefresh` | enum | Outcome of comparing a tracked index entry to its worktree path for staging refresh. | [API](https://docs.rs/grit-lib/latest/grit_lib/diff/enum.WorktreeAddRefresh.html) |
| `grit_lib::diff::WorktreeAddRefreshParams` | struct | Inputs for classify_worktree_entry_for_add. | [API](https://docs.rs/grit-lib/latest/grit_lib/diff/struct.WorktreeAddRefreshParams.html) |
| `grit_lib::diff_indent_heuristic` | module | Git-compatible diff hunk sliding (xdl_change_compact) including the indent heuristic. | [API](https://docs.rs/grit-lib/latest/grit_lib/diff_indent_heuristic/index.html) |
| `grit_lib::diff_moved` | module | Move detection for git diff --color-moved, implementing the same behavior as git’s add_lines_to_move_detection + mark_color_as_moved + dim_moved_lines. | [API](https://docs.rs/grit-lib/latest/grit_lib/diff_moved/index.html) |
| `grit_lib::diff_moved::ColorMovedMode` | enum | --color-moved mode. | [API](https://docs.rs/grit-lib/latest/grit_lib/diff_moved/enum.ColorMovedMode.html) |
| `grit_lib::diff_moved::MovedClass` | enum | The color class assigned to one emitted line after move detection. | [API](https://docs.rs/grit-lib/latest/grit_lib/diff_moved/enum.MovedClass.html) |
| `grit_lib::diffing` | module | Diffing: tree/content diff, rename detection, diffstat, line-log, pickaxe bloom. | [API](https://docs.rs/grit-lib/latest/grit_lib/diffing/index.html) |
| `grit_lib::diffstat` | module | Git-compatible --stat / diffstat layout (width, name truncation, bar scaling). | [API](https://docs.rs/grit-lib/latest/grit_lib/diffstat/index.html) |
| `grit_lib::diffstat::DiffstatOptions` | struct | Options for laying out diffstat lines (Git diff_options stat fields). | [API](https://docs.rs/grit-lib/latest/grit_lib/diffstat/struct.DiffstatOptions.html) |
| `grit_lib::diffstat::FileStatInput` | struct | Default total width for format-patch diffstat (MAIL_DEFAULT_WRAP in Git). | [API](https://docs.rs/grit-lib/latest/grit_lib/diffstat/struct.FileStatInput.html) |
| `grit_lib::dotfile` | module | Git-compatible .git* / NTFS / HFS path checks (path.c, utf8.c). | [API](https://docs.rs/grit-lib/latest/grit_lib/dotfile/index.html) |
| `grit_lib::environment` | module | Explicit discovery and configuration environment for embedding callers. | [API](https://docs.rs/grit-lib/latest/grit_lib/environment/index.html) |
| `grit_lib::environment::Environment` | struct | Discovery and config variables that affect repository open/discover and ConfigSet loading. | [API](https://docs.rs/grit-lib/latest/grit_lib/environment/struct.Environment.html) |
| `grit_lib::environment::RepositoryOptions` | struct | Options passed to repository open/discover with an explicit Environment. | [API](https://docs.rs/grit-lib/latest/grit_lib/environment/struct.RepositoryOptions.html) |
| `grit_lib::error` | module | Shared error types for grit-lib. | [API](https://docs.rs/grit-lib/latest/grit_lib/error/index.html) |
| `grit_lib::error::BadNumericSource` | enum | Why a Git config numeric value was rejected (git config int strict parsing). | [API](https://docs.rs/grit-lib/latest/grit_lib/error/enum.BadNumericSource.html) |
| `grit_lib::error::ConfigError` | enum | Configuration parse and validation failures. | [API](https://docs.rs/grit-lib/latest/grit_lib/error/enum.ConfigError.html) |
| `grit_lib::error::DiffPathError` | enum | Path lookup failures while formatting a diff. | [API](https://docs.rs/grit-lib/latest/grit_lib/error/enum.DiffPathError.html) |
| `grit_lib::error::Error` | enum | The top-level error type for all grit-lib operations. | [API](https://docs.rs/grit-lib/latest/grit_lib/error/enum.Error.html) |
| `grit_lib::error::FilterError` | enum | Clean/smudge filter and EOL conversion failures. | [API](https://docs.rs/grit-lib/latest/grit_lib/error/enum.FilterError.html) |
| `grit_lib::error::FilterPhase` | enum | Which filter hook failed. | [API](https://docs.rs/grit-lib/latest/grit_lib/error/enum.FilterPhase.html) |
| `grit_lib::error::PathOutsideRepoError` | enum | Path outside the repository during pathspec or transport resolution. | [API](https://docs.rs/grit-lib/latest/grit_lib/error/enum.PathOutsideRepoError.html) |
| `grit_lib::error::RefLockError` | enum | Reference lock failures while creating or updating a ref. | [API](https://docs.rs/grit-lib/latest/grit_lib/error/enum.RefLockError.html) |
| `grit_lib::error::SparseCheckoutWarning` | enum | Sparse-checkout cone pattern parse warnings (non-fatal). | [API](https://docs.rs/grit-lib/latest/grit_lib/error/enum.SparseCheckoutWarning.html) |
| `grit_lib::fetch` | module | Wire-protocol fetch orchestration over a crate::transport::Connection. | [API](https://docs.rs/grit-lib/latest/grit_lib/fetch/index.html) |
| `grit_lib::fetch::NoProgress` | struct | A Progress that discards everything. | [API](https://docs.rs/grit-lib/latest/grit_lib/fetch/struct.NoProgress.html) |
| `grit_lib::fetch::Progress` | trait | Sink for the remote’s human-readable progress (side-band channel 2). | [API](https://docs.rs/grit-lib/latest/grit_lib/fetch/trait.Progress.html) |
| `grit_lib::fetch_head` | module | Parsing FETCH_HEAD lines. | [API](https://docs.rs/grit-lib/latest/grit_lib/fetch_head/index.html) |
| `grit_lib::fetch_negotiator` | module | Skipping fetch negotiator — implements Git’s “skipping” negotiation strategy. | [API](https://docs.rs/grit-lib/latest/grit_lib/fetch_negotiator/index.html) |
| `grit_lib::fetch_negotiator::SkippingNegotiator` | struct | Skipping algorithm negotiator for fetch have lines. | [API](https://docs.rs/grit-lib/latest/grit_lib/fetch_negotiator/struct.SkippingNegotiator.html) |
| `grit_lib::fetch_submodules` | module | Logic for git fetch --recurse-submodules (changed-submodule detection and config). | [API](https://docs.rs/grit-lib/latest/grit_lib/fetch_submodules/index.html) |
| `grit_lib::fetch_submodules::ChangedSubmoduleFetch` | struct | One submodule that gained new gitlink targets in rev-list <tips> --not <neg>. | [API](https://docs.rs/grit-lib/latest/grit_lib/fetch_submodules/struct.ChangedSubmoduleFetch.html) |
| `grit_lib::fetch_submodules::FetchRecurseSubmodules` | enum | fetch.recurseSubmodules / --recurse-submodules modes for fetch. | [API](https://docs.rs/grit-lib/latest/grit_lib/fetch_submodules/enum.FetchRecurseSubmodules.html) |
| `grit_lib::filter_process` | module | Long-running Git filter protocol (filter.<name>.process), matching git-filter v2. | [API](https://docs.rs/grit-lib/latest/grit_lib/filter_process/index.html) |
| `grit_lib::filter_process::DelayedCheckoutError` | enum | Failure from DelayedProcessCheckout::finish. | [API](https://docs.rs/grit-lib/latest/grit_lib/filter_process/enum.DelayedCheckoutError.html) |
| `grit_lib::filter_process::DelayedCheckoutProblem` | enum | One delayed-checkout outcome that would have been printed as Git’s error: ... | [API](https://docs.rs/grit-lib/latest/grit_lib/filter_process/enum.DelayedCheckoutProblem.html) |
| `grit_lib::filter_process::DelayedProcessCheckout` | struct | Paths waiting for list_available_blobs / retry smudge (Git finish_delayed_checkout). | [API](https://docs.rs/grit-lib/latest/grit_lib/filter_process/struct.DelayedProcessCheckout.html) |
| `grit_lib::filter_process::DelayedProcessCheckoutEntry` | struct | One path deferred by a process filter that returned status=delayed (Git delayed_checkout). | [API](https://docs.rs/grit-lib/latest/grit_lib/filter_process/struct.DelayedProcessCheckoutEntry.html) |
| `grit_lib::filter_process::FilterProcessState` | struct | Per-repository filter-process registry (long-running filter.*.process drivers). | [API](https://docs.rs/grit-lib/latest/grit_lib/filter_process/struct.FilterProcessState.html) |
| `grit_lib::filter_process::FilterSmudgeMeta` | struct | Optional metadata sent with smudge (ref, treeish, blob hex). | [API](https://docs.rs/grit-lib/latest/grit_lib/filter_process/struct.FilterSmudgeMeta.html) |
| `grit_lib::fmt_merge_msg` | module | Merge commit message formatter — git fmt-merge-msg logic. | [API](https://docs.rs/grit-lib/latest/grit_lib/fmt_merge_msg/index.html) |
| `grit_lib::fmt_merge_msg::FmtMergeMsgOptions` | struct | Options for fmt_merge_msg. | [API](https://docs.rs/grit-lib/latest/grit_lib/fmt_merge_msg/struct.FmtMergeMsgOptions.html) |
| `grit_lib::fsck_standalone` | module | Standalone object fsck for loose-object validation before hashing. | [API](https://docs.rs/grit-lib/latest/grit_lib/fsck_standalone/index.html) |
| `grit_lib::fsck_standalone::FsckError` | struct | Git-compatible fsck failure for loose object validation. | [API](https://docs.rs/grit-lib/latest/grit_lib/fsck_standalone/struct.FsckError.html) |
| `grit_lib::fsck_standalone::FsckObjectOptions` | struct | Repository hash width for object-id fields in commit, tag, and tree headers. | [API](https://docs.rs/grit-lib/latest/grit_lib/fsck_standalone/struct.FsckObjectOptions.html) |
| `grit_lib::gc` | module | In-process maintenance primitives that embedders such as jj use in place of shelling out to git gc / git remote show / gix::refs::transaction. | [API](https://docs.rs/grit-lib/latest/grit_lib/gc/index.html) |
| `grit_lib::gc::PruneStats` | struct | Result of a loose-object prune. | [API](https://docs.rs/grit-lib/latest/grit_lib/gc/struct.PruneStats.html) |
| `grit_lib::gc::RefTransactionItem` | struct | A single ref change in an update_refs batch transaction. | [API](https://docs.rs/grit-lib/latest/grit_lib/gc/struct.RefTransactionItem.html) |
| `grit_lib::git_binary_base85` | module | Base-85 codec for GIT binary patch sections (matches git/base85.c). | [API](https://docs.rs/grit-lib/latest/grit_lib/git_binary_base85/index.html) |
| `grit_lib::git_binary_base85::DecodeError` | enum | Errors returned while decoding a Git binary-patch base85 line. | [API](https://docs.rs/grit-lib/latest/grit_lib/git_binary_base85/enum.DecodeError.html) |
| `grit_lib::git_date` | module | Git-compatible date parsing and display. | [API](https://docs.rs/grit-lib/latest/grit_lib/git_date/index.html) |
| `grit_lib::git_date::TestToolDateResult` | enum | Result of test-tool date — either lines for stdout or a process exit code (no output). | [API](https://docs.rs/grit-lib/latest/grit_lib/git_date/enum.TestToolDateResult.html) |
| `grit_lib::git_date::approx` | module | Git-compatible approxidate parsing. | [API](https://docs.rs/grit-lib/latest/grit_lib/git_date/approx/index.html) |
| `grit_lib::git_date::parse` | module | Git-compatible date parsing (parse_date_basic, parse_date). | [API](https://docs.rs/grit-lib/latest/grit_lib/git_date/parse/index.html) |
| `grit_lib::git_date::parse::DateParseError` | struct | Date string could not be parsed. | [API](https://docs.rs/grit-lib/latest/grit_lib/git_date/parse/struct.DateParseError.html) |
| `grit_lib::git_date::show` | module | Git-compatible date display (show_date, show_date_relative, strftime handling). | [API](https://docs.rs/grit-lib/latest/grit_lib/git_date/show/index.html) |
| `grit_lib::git_date::tm` | module | Time conversion helpers that produce Git-compatible timestamps. | [API](https://docs.rs/grit-lib/latest/grit_lib/git_date/tm/index.html) |
| `grit_lib::git_path` | module | Git-compatible path normalization and helpers for test-tool path-utils. | [API](https://docs.rs/grit-lib/latest/grit_lib/git_path/index.html) |
| `grit_lib::git_path::GitPathError` | enum | Errors returned by Git-compatible path helper routines. | [API](https://docs.rs/grit-lib/latest/grit_lib/git_path/enum.GitPathError.html) |
| `grit_lib::gitmodules` | module | .gitmodules validation (Git fsck / submodule-config parity). | [API](https://docs.rs/grit-lib/latest/grit_lib/gitmodules/index.html) |
| `grit_lib::gitmodules::DotFsckIssue` | enum | Problems reported while walking trees / blobs for .gitmodules / .gitattributes fsck. | [API](https://docs.rs/grit-lib/latest/grit_lib/gitmodules/enum.DotFsckIssue.html) |
| `grit_lib::gitmodules::DotFsckTracker` | struct | Tracks .gitmodules / .gitattributes blob OIDs discovered in trees (Git fsck_options oidsets). | [API](https://docs.rs/grit-lib/latest/grit_lib/gitmodules/struct.DotFsckTracker.html) |
| `grit_lib::hash` | module | Incremental hashing for Git object ids and file trailers. | [API](https://docs.rs/grit-lib/latest/grit_lib/hash/index.html) |
| `grit_lib::hash::Backend` | enum | Which implementation the sha1 / sha2 dependency selects for algo on this CPU. | [API](https://docs.rs/grit-lib/latest/grit_lib/hash/enum.Backend.html) |
| `grit_lib::hash::HashingWriter` | struct | A writer that forwards bytes to an inner sink while accumulating a checksum. | [API](https://docs.rs/grit-lib/latest/grit_lib/hash/struct.HashingWriter.html) |
| `grit_lib::hash::ObjectHasher` | enum | Incremental hasher for Git’s supported object-id algorithms. | [API](https://docs.rs/grit-lib/latest/grit_lib/hash/enum.ObjectHasher.html) |
| `grit_lib::hash::ParallelHashError` | enum | Failure from try_par_hash_with when a closure returns an error. | [API](https://docs.rs/grit-lib/latest/grit_lib/hash/enum.ParallelHashError.html) |
| `grit_lib::hash::Parallelism` | struct | Resolved worker thread count for parallel hash helpers. | [API](https://docs.rs/grit-lib/latest/grit_lib/hash/struct.Parallelism.html) |
| `grit_lib::hash::TrailerMismatch` | struct | Checksum at the end of bytes did not match a digest of the leading body. | [API](https://docs.rs/grit-lib/latest/grit_lib/hash/struct.TrailerMismatch.html) |
| `grit_lib::hide_refs` | module | transfer.hideRefs / receive.hideRefs / uploadpack.hideRefs matching (Git ref_is_hidden). | [API](https://docs.rs/grit-lib/latest/grit_lib/hide_refs/index.html) |
| `grit_lib::hooks` | module | Hook execution utilities. | [API](https://docs.rs/grit-lib/latest/grit_lib/hooks/index.html) |
| `grit_lib::hooks::CommitHookEnv` | struct | Environment for commit-style hooks (GIT_INDEX_FILE, GIT_EDITOR, GIT_PREFIX, and extra pairs). | [API](https://docs.rs/grit-lib/latest/grit_lib/hooks/struct.CommitHookEnv.html) |
| `grit_lib::hooks::HookError` | enum | Hook subprocess failure (non-zero exit or spawn error). | [API](https://docs.rs/grit-lib/latest/grit_lib/hooks/enum.HookError.html) |
| `grit_lib::hooks::HookResult` | enum | Result of running a hook. | [API](https://docs.rs/grit-lib/latest/grit_lib/hooks/enum.HookResult.html) |
| `grit_lib::hooks::RunHookOptions` | struct | Options for run_hook_opts. | [API](https://docs.rs/grit-lib/latest/grit_lib/hooks/struct.RunHookOptions.html) |
| `grit_lib::ident` | module | Git author/committer identity lines (ident in Git’s fsck.c / commit.c). | [API](https://docs.rs/grit-lib/latest/grit_lib/ident/index.html) |
| `grit_lib::ident::ParsedSignatureTimes` | struct | Successful parse of the trailing <unix> <+HHMM> portion of a signature. | [API](https://docs.rs/grit-lib/latest/grit_lib/ident/struct.ParsedSignatureTimes.html) |
| `grit_lib::ident::SignatureTail` | enum | Distinguishes a non-numeric date field from a numeric field that fails Git’s overflow rules. | [API](https://docs.rs/grit-lib/latest/grit_lib/ident/enum.SignatureTail.html) |
| `grit_lib::ident::SignatureTimestamp` | enum | Parsed timestamp from a signature line for display and filtering. | [API](https://docs.rs/grit-lib/latest/grit_lib/ident/enum.SignatureTimestamp.html) |
| `grit_lib::ident_config` | module | Default identity values from config and the system (Git ident.c). | [API](https://docs.rs/grit-lib/latest/grit_lib/ident_config/index.html) |
| `grit_lib::ident_resolve` | module | Git-compatible author/committer identity resolution (see upstream ident.c). | [API](https://docs.rs/grit-lib/latest/grit_lib/ident_resolve/index.html) |
| `grit_lib::ident_resolve::GitIdentityNameEnv` | enum | Whether GIT_AUTHOR_NAME / GIT_COMMITTER_NAME is unset vs set (possibly empty). | [API](https://docs.rs/grit-lib/latest/grit_lib/ident_resolve/enum.GitIdentityNameEnv.html) |
| `grit_lib::ident_resolve::IdentRole` | enum | Author vs committer for GIT_* / author.* / committer.* lookup. | [API](https://docs.rs/grit-lib/latest/grit_lib/ident_resolve/enum.IdentRole.html) |
| `grit_lib::ident_resolve::IdentityEnv` | trait | Environment access used for identity resolution. | [API](https://docs.rs/grit-lib/latest/grit_lib/ident_resolve/trait.IdentityEnv.html) |
| `grit_lib::ident_resolve::IdentityError` | enum | Errors returned by strict identity resolution. | [API](https://docs.rs/grit-lib/latest/grit_lib/ident_resolve/enum.IdentityError.html) |
| `grit_lib::ignore` | module | Ignore and exclude matching for check-ignore. | [API](https://docs.rs/grit-lib/latest/grit_lib/ignore/index.html) |
| `grit_lib::ignore::IgnoreMatch` | struct | Metadata for a matching rule. | [API](https://docs.rs/grit-lib/latest/grit_lib/ignore/struct.IgnoreMatch.html) |
| `grit_lib::ignore::IgnoreMatcher` | struct | Engine used to evaluate ignore patterns against repository-relative paths. | [API](https://docs.rs/grit-lib/latest/grit_lib/ignore/struct.IgnoreMatcher.html) |
| `grit_lib::index` | module | Git index (staging area) reading and writing. | [API](https://docs.rs/grit-lib/latest/grit_lib/index/index.html) |
| `grit_lib::index::CacheTreeNode` | struct | One node from Git’s TREE index extension. | [API](https://docs.rs/grit-lib/latest/grit_lib/index/struct.CacheTreeNode.html) |
| `grit_lib::index::Index` | struct | The in-memory representation of the Git index file. | [API](https://docs.rs/grit-lib/latest/grit_lib/index/struct.Index.html) |
| `grit_lib::index::IndexEntry` | struct | A single entry in the Git index. | [API](https://docs.rs/grit-lib/latest/grit_lib/index/struct.IndexEntry.html) |
| `grit_lib::index::IndexLoadOptions` | struct | Options for loading an index from disk. | [API](https://docs.rs/grit-lib/latest/grit_lib/index/struct.IndexLoadOptions.html) |
| `grit_lib::index::IndexStatFields` | struct | Stat fields copied from a worktree Metadata probe during index staging. | [API](https://docs.rs/grit-lib/latest/grit_lib/index/struct.IndexStatFields.html) |
| `grit_lib::index::StatMatchPolicy` | struct | Git match_stat_data policy (core.trustctime, core.checkstat, core.usenanosec). | [API](https://docs.rs/grit-lib/latest/grit_lib/index/struct.StatMatchPolicy.html) |
| `grit_lib::index_name_hash_lazy` | module | Lazy, optionally multi-threaded index name/dir hash initialization compatible with Git’s name-hash.c (used by test-tool lazy-init-name-hash and regression test t3008). | [API](https://docs.rs/grit-lib/latest/grit_lib/index_name_hash_lazy/index.html) |
| `grit_lib::index_pack` | module | Install a received packfile into the object store (index-pack path). | [API](https://docs.rs/grit-lib/latest/grit_lib/index_pack/index.html) |
| `grit_lib::index_pack::IngestPackOptions` | struct | Options controlling how a received pack is ingested. | [API](https://docs.rs/grit-lib/latest/grit_lib/index_pack/struct.IngestPackOptions.html) |
| `grit_lib::index_pack::IngestedPack` | struct | Result of installing a pack under objects/pack/. | [API](https://docs.rs/grit-lib/latest/grit_lib/index_pack/struct.IngestedPack.html) |
| `grit_lib::init_filesystem` | module | Filesystem capability probes during repository initialization. | [API](https://docs.rs/grit-lib/latest/grit_lib/init_filesystem/index.html) |
| `grit_lib::init_filesystem::InitFilesystemConfigOptions` | struct | Controls when init-time filesystem probes may write local config. | [API](https://docs.rs/grit-lib/latest/grit_lib/init_filesystem/struct.InitFilesystemConfigOptions.html) |
| `grit_lib::interpret_trailers` | module | Commit message trailer parsing and rewriting (Git-compatible). | [API](https://docs.rs/grit-lib/latest/grit_lib/interpret_trailers/index.html) |
| `grit_lib::interpret_trailers::NewTrailerArg` | struct | Placement of a new trailer relative to an anchor trailer. | [API](https://docs.rs/grit-lib/latest/grit_lib/interpret_trailers/struct.NewTrailerArg.html) |
| `grit_lib::line_log` | module | Line-level history (git log -L) — range tracking across diffs. | [API](https://docs.rs/grit-lib/latest/grit_lib/line_log/index.html) |
| `grit_lib::line_log::DiffHunk` | struct | One aligned parent/target hunk from a line diff (half-open line indices). | [API](https://docs.rs/grit-lib/latest/grit_lib/line_log/struct.DiffHunk.html) |
| `grit_lib::line_log::DiffRanges` | struct | Sequence of hunks from collect_diff_ranges (parent[i] aligns with target[i]). | [API](https://docs.rs/grit-lib/latest/grit_lib/line_log/struct.DiffRanges.html) |
| `grit_lib::line_log::LineLogDisplay` | struct | Captured diff input for format_line_log_diff (one file per hunk group). | [API](https://docs.rs/grit-lib/latest/grit_lib/line_log/struct.LineLogDisplay.html) |
| `grit_lib::line_log::LineLogFile` | struct | One tracked file with 0-based half-open line ranges. | [API](https://docs.rs/grit-lib/latest/grit_lib/line_log/struct.LineLogFile.html) |
| `grit_lib::line_log::Range` | struct | Half-open line range using 0-based indices (Git internal). | [API](https://docs.rs/grit-lib/latest/grit_lib/line_log/struct.Range.html) |
| `grit_lib::line_log::RangeSet` | struct | Sorted, disjoint, non-empty ranges. | [API](https://docs.rs/grit-lib/latest/grit_lib/line_log/struct.RangeSet.html) |
| `grit_lib::mailmap` | module | Parse .mailmap and resolve author/committer identities (Git-compatible). | [API](https://docs.rs/grit-lib/latest/grit_lib/mailmap/index.html) |
| `grit_lib::mailmap::MailmapEntry` | struct | Legacy line-shaped entry kept for API compatibility; prefer MailmapTable. | [API](https://docs.rs/grit-lib/latest/grit_lib/mailmap/struct.MailmapEntry.html) |
| `grit_lib::mailmap::MailmapTable` | struct | Parsed mailmap as a lookup table (Git string_list + nested namemap). | [API](https://docs.rs/grit-lib/latest/grit_lib/mailmap/struct.MailmapTable.html) |
| `grit_lib::merge_base` | module | Merge-base and reachability primitives. | [API](https://docs.rs/grit-lib/latest/grit_lib/merge_base/index.html) |
| `grit_lib::merge_base::MergeBaseForDiffError` | enum | Failure modes for merge_base_for_diff_index and merge_base_for_diff_two_commits. | [API](https://docs.rs/grit-lib/latest/grit_lib/merge_base/enum.MergeBaseForDiffError.html) |
| `grit_lib::merge_base::ReachableWalkLimit` | enum | Commits reachable from tips that are not ancestors of any hide tip, in committer-date order (newest first). | [API](https://docs.rs/grit-lib/latest/grit_lib/merge_base/enum.ReachableWalkLimit.html) |
| `grit_lib::merge_diff` | module | Merge commit and combined (--cc / -c) diff helpers. | [API](https://docs.rs/grit-lib/latest/grit_lib/merge_diff/index.html) |
| `grit_lib::merge_file` | module | Three-way file merge — the engine behind grit merge-file. | [API](https://docs.rs/grit-lib/latest/grit_lib/merge_file/index.html) |
| `grit_lib::merge_file::ConflictStyle` | enum | Conflict-marker output style. | [API](https://docs.rs/grit-lib/latest/grit_lib/merge_file/enum.ConflictStyle.html) |
| `grit_lib::merge_file::MergeFavor` | enum | How conflict regions should be resolved. | [API](https://docs.rs/grit-lib/latest/grit_lib/merge_file/enum.MergeFavor.html) |
| `grit_lib::merge_file::MergeInput` | struct | Input and options for a three-way merge. | [API](https://docs.rs/grit-lib/latest/grit_lib/merge_file/struct.MergeInput.html) |
| `grit_lib::merge_file::MergeOutput` | struct | Result of a three-way merge. | [API](https://docs.rs/grit-lib/latest/grit_lib/merge_file/struct.MergeOutput.html) |
| `grit_lib::merge_trees` | module | Rename-aware three-way tree merge for cherry-pick / revert style merges. | [API](https://docs.rs/grit-lib/latest/grit_lib/merge_trees/index.html) |
| `grit_lib::merge_trees::TreeMergeConflictPresentation` | struct | Labels and marker style for conflict output during tree merges. | [API](https://docs.rs/grit-lib/latest/grit_lib/merge_trees/struct.TreeMergeConflictPresentation.html) |
| `grit_lib::merge_trees::TreeMergeOutput` | struct | Result of merging three trees with optional conflict-marker blobs for checkout. | [API](https://docs.rs/grit-lib/latest/grit_lib/merge_trees/struct.TreeMergeOutput.html) |
| `grit_lib::merge_trees::WhitespaceMergeOptions` | struct | How to label the “theirs” side in textual conflict markers. | [API](https://docs.rs/grit-lib/latest/grit_lib/merge_trees/struct.WhitespaceMergeOptions.html) |
| `grit_lib::merging` | module | Merging: merge-base, tree/file merges, rerere, merge-message formatting. | [API](https://docs.rs/grit-lib/latest/grit_lib/merging/index.html) |
| `grit_lib::midx` | module | Multi-pack-index (MIDX) file writing and minimal reading. | [API](https://docs.rs/grit-lib/latest/grit_lib/midx/index.html) |
| `grit_lib::midx::CompactError` | enum | Failure modes of compact_multi_pack_index, each mapping to one of git’s user-facing diagnostics in cmd_multi_pack_index_compact. | [API](https://docs.rs/grit-lib/latest/grit_lib/midx/enum.CompactError.html) |
| `grit_lib::midx::MidxBitmapWriteOutcome` | enum | Outcome of an optional MIDX reachability bitmap write. | [API](https://docs.rs/grit-lib/latest/grit_lib/midx/enum.MidxBitmapWriteOutcome.html) |
| `grit_lib::midx::MidxBtmpPackRange` | struct | One pack’s slice of the MIDX pseudo-bitmap namespace (BTMP chunk). | [API](https://docs.rs/grit-lib/latest/grit_lib/midx/struct.MidxBtmpPackRange.html) |
| `grit_lib::midx::MidxObjectRef` | struct | A single MIDX-referenced object together with the pack it is attributed to. | [API](https://docs.rs/grit-lib/latest/grit_lib/midx/struct.MidxObjectRef.html) |
| `grit_lib::midx::MidxReuseTables` | struct | OID rows from the active multi-pack-index, plus reverse-index order for pack-reuse bitmap bits. | [API](https://docs.rs/grit-lib/latest/grit_lib/midx/struct.MidxReuseTables.html) |
| `grit_lib::midx::WriteMultiPackIndexOptions` | struct | Options for writing a multi-pack index (extension of the simple writer). | [API](https://docs.rs/grit-lib/latest/grit_lib/midx/struct.WriteMultiPackIndexOptions.html) |
| `grit_lib::midx::WriteMultiPackIndexResult` | struct | Result of write_multi_pack_index_with_options. | [API](https://docs.rs/grit-lib/latest/grit_lib/midx/struct.WriteMultiPackIndexResult.html) |
| `grit_lib::midx_error` | module | Typed errors for multi-pack-index load and verification. | [API](https://docs.rs/grit-lib/latest/grit_lib/midx_error/index.html) |
| `grit_lib::midx_error::MidxError` | enum | Unified diff / patch application errors. | [API](https://docs.rs/grit-lib/latest/grit_lib/error/../midx_error/enum.MidxError.html) |
| `grit_lib::midx_error::MidxError` | enum | A fatal multi-pack-index condition (Git die() after error: lines). | [API](https://docs.rs/grit-lib/latest/grit_lib/midx_error/enum.MidxError.html) |
| `grit_lib::name_rev` | module | Name-rev: name commits relative to refs. | [API](https://docs.rs/grit-lib/latest/grit_lib/name_rev/index.html) |
| `grit_lib::name_rev::NameRevOptions` | struct | Options that control which refs participate in naming. | [API](https://docs.rs/grit-lib/latest/grit_lib/name_rev/struct.NameRevOptions.html) |
| `grit_lib::net_trace` | module | Network operation tracing through crate::diagnostics::Trace::Network. | [API](https://docs.rs/grit-lib/latest/grit_lib/net_trace/index.html) |
| `grit_lib::notes` | module | git notes tree manipulation — the fanout tree mapping object -> note blob. | [API](https://docs.rs/grit-lib/latest/grit_lib/notes/index.html) |
| `grit_lib::notes::NotesTreeEntry` | struct | Per-worktree subdirectory holding the conflicted note blobs during a notes merge. | [API](https://docs.rs/grit-lib/latest/grit_lib/notes/struct.NotesTreeEntry.html) |
| `grit_lib::object_store` | module | Object storage: ids/kinds, the object database, packs, multi-pack index, deltas. | [API](https://docs.rs/grit-lib/latest/grit_lib/object_store/index.html) |
| `grit_lib::objects` | module | Git object model: object IDs, kinds, and in-memory representations. | [API](https://docs.rs/grit-lib/latest/grit_lib/objects/index.html) |
| `grit_lib::objects::CommitData` | struct | Parsed representation of a commit object. | [API](https://docs.rs/grit-lib/latest/grit_lib/objects/struct.CommitData.html) |
| `grit_lib::objects::HashAlgo` | enum | A Git hash algorithm. | [API](https://docs.rs/grit-lib/latest/grit_lib/objects/enum.HashAlgo.html) |
| `grit_lib::objects::HashVersionError` | struct | Error when converting an on-disk hash-version byte to HashAlgo. | [API](https://docs.rs/grit-lib/latest/grit_lib/objects/struct.HashVersionError.html) |
| `grit_lib::objects::Object` | struct | A decompressed, header-stripped Git object. | [API](https://docs.rs/grit-lib/latest/grit_lib/objects/struct.Object.html) |
| `grit_lib::objects::ObjectId` | struct | A Git object identifier: a SHA-1 (20-byte) or SHA-256 (32-byte) digest. | [API](https://docs.rs/grit-lib/latest/grit_lib/objects/struct.ObjectId.html) |
| `grit_lib::objects::ObjectInfo` | struct | Kind and uncompressed size of a Git object without loading its payload. | [API](https://docs.rs/grit-lib/latest/grit_lib/objects/struct.ObjectInfo.html) |
| `grit_lib::objects::ObjectKind` | enum | The four Git object types. | [API](https://docs.rs/grit-lib/latest/grit_lib/objects/enum.ObjectKind.html) |
| `grit_lib::objects::TagData` | struct | Parsed representation of an annotated tag object. | [API](https://docs.rs/grit-lib/latest/grit_lib/objects/struct.TagData.html) |
| `grit_lib::objects::TreeEntry` | struct | A single entry in a Git tree object. | [API](https://docs.rs/grit-lib/latest/grit_lib/objects/struct.TreeEntry.html) |
| `grit_lib::odb` | module | Loose object database: reading and writing zlib-compressed Git objects. | [API](https://docs.rs/grit-lib/latest/grit_lib/odb/index.html) |
| `grit_lib::odb::LooseStore` | struct | On-disk loose object store for one objects/ directory. | [API](https://docs.rs/grit-lib/latest/grit_lib/odb/struct.LooseStore.html) |
| `grit_lib::odb::LooseStore` | struct | Loose-object storage under objects/xx/<suffix> (zlib-compressed Git objects). | [API](https://docs.rs/grit-lib/latest/grit_lib/odb/store/../struct.LooseStore.html) |
| `grit_lib::odb::MemoryStore` | struct | In-memory object map keyed by ObjectId. | [API](https://docs.rs/grit-lib/latest/grit_lib/odb/struct.MemoryStore.html) |
| `grit_lib::odb::ObjectStore` | trait | Read-only object storage: lookup, metadata, streaming, and enumeration. | [API](https://docs.rs/grit-lib/latest/grit_lib/odb/trait.ObjectStore.html) |
| `grit_lib::odb::Odb` | struct | A loose-object database rooted at a given objects/ directory. | [API](https://docs.rs/grit-lib/latest/grit_lib/odb/struct.Odb.html) |
| `grit_lib::odb::OdbBuilder` | struct | Configure and construct an Odb with a pluggable primary backend. | [API](https://docs.rs/grit-lib/latest/grit_lib/odb/struct.OdbBuilder.html) |
| `grit_lib::odb::WritableObjectStore` | trait | Object storage that supports inserting new objects. | [API](https://docs.rs/grit-lib/latest/grit_lib/odb/trait.WritableObjectStore.html) |
| `grit_lib::odb::WriteOptions` | struct | Options for Odb::write_with_options. | [API](https://docs.rs/grit-lib/latest/grit_lib/odb/struct.WriteOptions.html) |
| `grit_lib::odb::builder` | module | Build an Odb with a custom primary store and optional read overlays. | [API](https://docs.rs/grit-lib/latest/grit_lib/odb/builder/index.html) |
| `grit_lib::odb::builder::OdbBuilder` | struct | Configure and construct an Odb with a pluggable primary backend. | [API](https://docs.rs/grit-lib/latest/grit_lib/odb/builder/struct.OdbBuilder.html) |
| `grit_lib::odb::store` | module | Pluggable object storage backends and the ObjectStore trait surface. | [API](https://docs.rs/grit-lib/latest/grit_lib/odb/store/index.html) |
| `grit_lib::odb::store::CompositeStore` | struct | Build an Odb with a custom primary store and optional read overlays. | [API](https://docs.rs/grit-lib/latest/grit_lib/odb/store/struct.CompositeStore.html) |
| `grit_lib::odb::store::CompositeStore` | struct | Read-only store that consults an ordered list of backends. | [API](https://docs.rs/grit-lib/latest/grit_lib/odb/store/struct.CompositeStore.html) |
| `grit_lib::odb::store::FilesSource` | struct | Read/write object storage backed by one objects/ directory tree. | [API](https://docs.rs/grit-lib/latest/grit_lib/odb/store/struct.FilesSource.html) |
| `grit_lib::odb::store::MemoryStore` | struct | In-memory object map keyed by ObjectId. | [API](https://docs.rs/grit-lib/latest/grit_lib/odb/store/struct.MemoryStore.html) |
| `grit_lib::odb::store::MidxObjects` | struct | MIDX-backed read-only ObjectStore for one objects/ directory. | [API](https://docs.rs/grit-lib/latest/grit_lib/odb/store/struct.MidxObjects.html) |
| `grit_lib::odb::store::MidxObjectsStatus` | enum | Whether MidxObjects can serve reads for this repository. | [API](https://docs.rs/grit-lib/latest/grit_lib/odb/store/enum.MidxObjectsStatus.html) |
| `grit_lib::odb::store::ObjectStore` | trait | Read-only object storage: lookup, metadata, streaming, and enumeration. | [API](https://docs.rs/grit-lib/latest/grit_lib/odb/store/trait.ObjectStore.html) |
| `grit_lib::odb::store::ObjectStream` | struct | Streaming handle for a single object’s uncompressed payload. | [API](https://docs.rs/grit-lib/latest/grit_lib/odb/store/struct.ObjectStream.html) |
| `grit_lib::odb::store::PackFilter` | struct | Which local pack indexes participate in filtered membership checks. | [API](https://docs.rs/grit-lib/latest/grit_lib/odb/store/struct.PackFilter.html) |
| `grit_lib::odb::store::PackedObjects` | struct | Pack-index-backed read-only ObjectStore for one objects/ directory. | [API](https://docs.rs/grit-lib/latest/grit_lib/odb/store/struct.PackedObjects.html) |
| `grit_lib::odb::store::WritableObjectStore` | trait | Object storage that supports inserting new objects. | [API](https://docs.rs/grit-lib/latest/grit_lib/odb/store/trait.WritableObjectStore.html) |
| `grit_lib::odb::store::loose` | module | Loose-object storage under objects/xx/<suffix> (zlib-compressed Git objects). | [API](https://docs.rs/grit-lib/latest/grit_lib/odb/store/loose/index.html) |
| `grit_lib::odb::store::loose::LooseStore` | struct | On-disk loose object store for one objects/ directory. | [API](https://docs.rs/grit-lib/latest/grit_lib/odb/store/loose/struct.LooseStore.html) |
| `grit_lib::pack` | module | Pack and pack-index helpers for object counting and verification. | [API](https://docs.rs/grit-lib/latest/grit_lib/pack/index.html) |
| `grit_lib::pack::LocalPackInfo` | struct | Basic information about local packs. | [API](https://docs.rs/grit-lib/latest/grit_lib/pack/struct.LocalPackInfo.html) |
| `grit_lib::pack::PackData` | struct | Immutable bytes of a .pack or MIDX file. | [API](https://docs.rs/grit-lib/latest/grit_lib/pack/struct.PackData.html) |
| `grit_lib::pack::PackIndex` | struct | Parsed pack index with fanout-accelerated OID lookup and in-place table reads. | [API](https://docs.rs/grit-lib/latest/grit_lib/pack/struct.PackIndex.html) |
| `grit_lib::pack::PackIndexEntry` | struct | Owned pack index row (collect from PackIndex::iter when needed). | [API](https://docs.rs/grit-lib/latest/grit_lib/pack/struct.PackIndexEntry.html) |
| `grit_lib::pack::PackIndexEntryRef` | struct | Borrowed view of one row in a pack index. | [API](https://docs.rs/grit-lib/latest/grit_lib/pack/struct.PackIndexEntryRef.html) |
| `grit_lib::pack::PackLookupOptions` | struct | Options controlling which local packs participate in a lookup pass. | [API](https://docs.rs/grit-lib/latest/grit_lib/pack/struct.PackLookupOptions.html) |
| `grit_lib::pack::PackedDeltaDependency` | enum | Dependency of a packed delta object at object_offset within pack_bytes. | [API](https://docs.rs/grit-lib/latest/grit_lib/pack/enum.PackedDeltaDependency.html) |
| `grit_lib::pack::PackedType` | enum | A pack object type as encoded in the packed stream header. | [API](https://docs.rs/grit-lib/latest/grit_lib/pack/enum.PackedType.html) |
| `grit_lib::pack::VerifyObjectRecord` | struct | A decoded object header record used by verify-pack. | [API](https://docs.rs/grit-lib/latest/grit_lib/pack/struct.VerifyObjectRecord.html) |
| `grit_lib::pack_bitmap` | module | Read Git pack and multi-pack-index reachability bitmaps (.bitmap / BITM v1). | [API](https://docs.rs/grit-lib/latest/grit_lib/pack_bitmap/index.html) |
| `grit_lib::pack_bitmap::BitmapError` | enum | Failure mode when a .bitmap sidecar cannot be used. | [API](https://docs.rs/grit-lib/latest/grit_lib/pack_bitmap/enum.BitmapError.html) |
| `grit_lib::pack_bitmap::BitmapIndex` | struct | Memory-mapped pack or MIDX reachability bitmap (Git BITM v1). | [API](https://docs.rs/grit-lib/latest/grit_lib/pack_bitmap/struct.BitmapIndex.html) |
| `grit_lib::pack_bitmap::BitmapIndexCache` | struct | Repository-scoped cache slot for BitmapIndex::open. | [API](https://docs.rs/grit-lib/latest/grit_lib/pack_bitmap/struct.BitmapIndexCache.html) |
| `grit_lib::pack_bitmap::CommitReachabilityBitmap` | struct | Decoded reachability set for one commit (bits index pack/MIDX object positions). | [API](https://docs.rs/grit-lib/latest/grit_lib/pack_bitmap/struct.CommitReachabilityBitmap.html) |
| `grit_lib::pack_bitmap::MidxBitmapWriter` | struct | Writes .bitmap sidecars for multi-pack-index files (MIDX checksum in header). | [API](https://docs.rs/grit-lib/latest/grit_lib/pack_bitmap/struct.MidxBitmapWriter.html) |
| `grit_lib::pack_bitmap::PackBitmapWriteError` | enum | Failure while writing a pack reachability bitmap. | [API](https://docs.rs/grit-lib/latest/grit_lib/pack_bitmap/enum.PackBitmapWriteError.html) |
| `grit_lib::pack_bitmap::PackBitmapWriteOptions` | struct | Options controlling pack bitmap generation (caller-supplied; not read from the environment). | [API](https://docs.rs/grit-lib/latest/grit_lib/pack_bitmap/struct.PackBitmapWriteOptions.html) |
| `grit_lib::pack_bitmap::PackBitmapWriter` | struct | Writes .bitmap sidecars for pack indexes produced by all-into-one repacks. | [API](https://docs.rs/grit-lib/latest/grit_lib/pack_bitmap/struct.PackBitmapWriter.html) |
| `grit_lib::pack_bitmap::TypeBitmap` | struct | Borrowed type filter bitmap (commits, trees, blobs, or tags). | [API](https://docs.rs/grit-lib/latest/grit_lib/pack_bitmap/struct.TypeBitmap.html) |
| `grit_lib::pack_name_hash` | module | Git pack bitmap name-hash functions (pack_name_hash / pack_name_hash_v2). | [API](https://docs.rs/grit-lib/latest/grit_lib/pack_name_hash/index.html) |
| `grit_lib::pack_object_select` | module | Object selection for pack-objects (walk or pack bitmap reachability). | [API](https://docs.rs/grit-lib/latest/grit_lib/pack_object_select/index.html) |
| `grit_lib::pack_object_select::PackEnumerateOptions` | struct | Parameters for enumerate_pack_objects. | [API](https://docs.rs/grit-lib/latest/grit_lib/pack_object_select/struct.PackEnumerateOptions.html) |
| `grit_lib::pack_object_select::PackObjectSelection` | struct | Objects to emit in a negotiated pack plus peer-held closure for thin deltas. | [API](https://docs.rs/grit-lib/latest/grit_lib/pack_object_select/struct.PackObjectSelection.html) |
| `grit_lib::pack_objects` | module | Negotiation-driven pack-objects: enumerate wants minus haves, delta search, stream PACK v2. | [API](https://docs.rs/grit-lib/latest/grit_lib/pack_objects/index.html) |
| `grit_lib::pack_objects::PackBuildOptions` | struct | Options controlling pack-objects output (also used by build_pack). | [API](https://docs.rs/grit-lib/latest/grit_lib/pack_objects/struct.PackBuildOptions.html) |
| `grit_lib::pack_objects::PackBuildOptions` | struct | Identity and message for clone reflog entries written by the library. | [API](https://docs.rs/grit-lib/latest/grit_lib/transfer/../pack_objects/struct.PackBuildOptions.html) |
| `grit_lib::pack_objects::PackObjects` | struct | Streaming pack-objects builder over an Odb. | [API](https://docs.rs/grit-lib/latest/grit_lib/pack_objects/struct.PackObjects.html) |
| `grit_lib::pack_objects::PackObjectsOptions` | struct | Extended options for PackObjects. | [API](https://docs.rs/grit-lib/latest/grit_lib/pack_objects/struct.PackObjectsOptions.html) |
| `grit_lib::pack_objects::PackProgress` | enum | Progress hook for long pack builds. | [API](https://docs.rs/grit-lib/latest/grit_lib/pack_objects/enum.PackProgress.html) |
| `grit_lib::pack_objects::PackStats` | struct | Counters reported after a successful pack write. | [API](https://docs.rs/grit-lib/latest/grit_lib/pack_objects/struct.PackStats.html) |
| `grit_lib::pack_receive` | module | Stream side-band pack data from fetch/clone into memory or a pack temp file. | [API](https://docs.rs/grit-lib/latest/grit_lib/pack_receive/index.html) |
| `grit_lib::pack_receive::PackReceiveTarget` | enum | Where demuxed pack bytes are stored. | [API](https://docs.rs/grit-lib/latest/grit_lib/pack_receive/enum.PackReceiveTarget.html) |
| `grit_lib::pack_receive::TempPackReceive` | struct | A temp pack file under objects/pack/ for streaming clone/fetch receive. | [API](https://docs.rs/grit-lib/latest/grit_lib/pack_receive/struct.TempPackReceive.html) |
| `grit_lib::pack_reuse` | module | Verbatim pack reuse for bitmap-accelerated upload-pack (streaming PACK v2). | [API](https://docs.rs/grit-lib/latest/grit_lib/pack_reuse/index.html) |
| `grit_lib::pack_reuse::ReuseWriteStats` | struct | Counters updated while streaming reused pack bytes. | [API](https://docs.rs/grit-lib/latest/grit_lib/pack_reuse/struct.ReuseWriteStats.html) |
| `grit_lib::pack_reuse::StreamingReuse` | struct | Active verbatim reuse context while streaming a pack body. | [API](https://docs.rs/grit-lib/latest/grit_lib/pack_reuse/struct.StreamingReuse.html) |
| `grit_lib::pack_rev` | module | On-disk pack reverse index (.rev) — RIDX format matching Git’s pack-write.c. | [API](https://docs.rs/grit-lib/latest/grit_lib/pack_rev/index.html) |
| `grit_lib::pack_store` | module | Repository-scoped pack and MIDX read caches. | [API](https://docs.rs/grit-lib/latest/grit_lib/pack_store/index.html) |
| `grit_lib::pack_store::PackStore` | struct | Per-objects/ cache of pack indexes, bytes, MIDX views, and delta-base LRU state. | [API](https://docs.rs/grit-lib/latest/grit_lib/pack_store/struct.PackStore.html) |
| `grit_lib::patch_ids` | module | Patch-ID computation for commit equivalence detection. | [API](https://docs.rs/grit-lib/latest/grit_lib/patch_ids/index.html) |
| `grit_lib::patch_ids::PatchIdMode` | enum | How to compute a patch-ID from unified diff text. | [API](https://docs.rs/grit-lib/latest/grit_lib/patch_ids/enum.PatchIdMode.html) |
| `grit_lib::path` | module | Git-compatible verification of tree/index path components. | [API](https://docs.rs/grit-lib/latest/grit_lib/path/index.html) |
| `grit_lib::path::PathProtection` | struct | Path protection settings from core.protectHFS / core.protectNTFS. | [API](https://docs.rs/grit-lib/latest/grit_lib/path/struct.PathProtection.html) |
| `grit_lib::path_icase` | module | Case-insensitive path identity when core.ignorecase is enabled. | [API](https://docs.rs/grit-lib/latest/grit_lib/path_icase/index.html) |
| `grit_lib::path_icase::Stage0IcasePathMap` | struct | Map from case-folded path hash buckets to index spellings (built once per staging batch). | [API](https://docs.rs/grit-lib/latest/grit_lib/path_icase/struct.Stage0IcasePathMap.html) |
| `grit_lib::path_icase::Stage0TrackedPaths` | struct | Stage-0 tracked paths for O(1) average lookups during untracked scans. | [API](https://docs.rs/grit-lib/latest/grit_lib/path_icase/struct.Stage0TrackedPaths.html) |
| `grit_lib::path_walk` | module | Path-batched object graph walk matching Git’s walk_objects_by_path / test-tool path-walk. | [API](https://docs.rs/grit-lib/latest/grit_lib/path_walk/index.html) |
| `grit_lib::path_walk::PathWalkCounts` | struct | One line of test-tool path-walk output (excluding trailing summary lines). | [API](https://docs.rs/grit-lib/latest/grit_lib/path_walk/struct.PathWalkCounts.html) |
| `grit_lib::path_walk::PathWalkOptions` | struct | Options for walk_objects_by_path, aligned with Git’s struct path_walk_info. | [API](https://docs.rs/grit-lib/latest/grit_lib/path_walk/struct.PathWalkOptions.html) |
| `grit_lib::pathspec` | module | Git-compatible pathspec matching (magic tokens and global flags). | [API](https://docs.rs/grit-lib/latest/grit_lib/pathspec/index.html) |
| `grit_lib::pathspec::PathOutsideRepository` | struct | Resolved path lies outside the repository work tree (Git prefix_path_gently failure). | [API](https://docs.rs/grit-lib/latest/grit_lib/pathspec/struct.PathOutsideRepository.html) |
| `grit_lib::pathspec::PathspecMatchContext` | struct | Optional path metadata for literal pathspecs with a trailing / (tree-walk / diff-tree). | [API](https://docs.rs/grit-lib/latest/grit_lib/pathspec/struct.PathspecMatchContext.html) |
| `grit_lib::pkt_line` | module | Git pkt-line format helpers. | [API](https://docs.rs/grit-lib/latest/grit_lib/pkt_line/index.html) |
| `grit_lib::pkt_line::Packet` | enum | A single packet read from the wire. | [API](https://docs.rs/grit-lib/latest/grit_lib/pkt_line/enum.Packet.html) |
| `grit_lib::pkt_line::SidebandChannel1Writer` | struct | Incrementally frame pack bytes on sideband channel 1 (64k pkt-lines). | [API](https://docs.rs/grit-lib/latest/grit_lib/pkt_line/struct.SidebandChannel1Writer.html) |
| `grit_lib::plumbing` | module | Plumbing operations — low-level, machine-stable building blocks that map ~1:1 to a Git plumbing command (e.g. | [API](https://docs.rs/grit-lib/latest/grit_lib/plumbing/index.html) |
| `grit_lib::porcelain` | module | Porcelain operations — user-facing engines that assemble a structured result model from plumbing pieces (e.g. | [API](https://docs.rs/grit-lib/latest/grit_lib/porcelain/index.html) |
| `grit_lib::porcelain::add` | module | Stage working-tree changes into the index (git add). | [API](https://docs.rs/grit-lib/latest/grit_lib/porcelain/add/index.html) |
| `grit_lib::porcelain::add::StageMode` | enum | What paths stage should update (git add vs git add -u). | [API](https://docs.rs/grit-lib/latest/grit_lib/porcelain/add/enum.StageMode.html) |
| `grit_lib::porcelain::add::StageOptions` | struct | Inputs for stage. | [API](https://docs.rs/grit-lib/latest/grit_lib/porcelain/add/struct.StageOptions.html) |
| `grit_lib::porcelain::add::StageOutcome` | struct | Counts returned by stage. | [API](https://docs.rs/grit-lib/latest/grit_lib/porcelain/add/struct.StageOutcome.html) |
| `grit_lib::porcelain::checkout` | module | git checkout worktree-apply primitives. | [API](https://docs.rs/grit-lib/latest/grit_lib/porcelain/checkout/index.html) |
| `grit_lib::porcelain::cherry_pick` | module | git cherry-pick / git revert pick-engine core. | [API](https://docs.rs/grit-lib/latest/grit_lib/porcelain/cherry_pick/index.html) |
| `grit_lib::porcelain::cherry_pick::WhitespaceStrategyOptions` | struct | Whitespace-handling flags parsed from -X<option> merge-strategy options. | [API](https://docs.rs/grit-lib/latest/grit_lib/porcelain/cherry_pick/struct.WhitespaceStrategyOptions.html) |
| `grit_lib::porcelain::commit` | module | Create a commit from the current index and move the checked-out branch. | [API](https://docs.rs/grit-lib/latest/grit_lib/porcelain/commit/index.html) |
| `grit_lib::porcelain::commit::CommitOutcome` | struct | Result of create_commit. | [API](https://docs.rs/grit-lib/latest/grit_lib/porcelain/commit/struct.CommitOutcome.html) |
| `grit_lib::porcelain::commit::CommitRequest` | struct | Inputs for create_commit. | [API](https://docs.rs/grit-lib/latest/grit_lib/porcelain/commit/struct.CommitRequest.html) |
| `grit_lib::porcelain::log` | module | git log ref decoration as structured data. | [API](https://docs.rs/grit-lib/latest/grit_lib/porcelain/log/index.html) |
| `grit_lib::porcelain::log::DecorationFilter` | struct | The --decorate-refs / --decorate-refs-exclude / log.excludeDecoration ref filter. | [API](https://docs.rs/grit-lib/latest/grit_lib/porcelain/log/struct.DecorationFilter.html) |
| `grit_lib::porcelain::log::DecorationItem` | struct | One ref (or synthetic label) attached to a commit for --decorate / %d. | [API](https://docs.rs/grit-lib/latest/grit_lib/porcelain/log/struct.DecorationItem.html) |
| `grit_lib::porcelain::log::DecorationKind` | enum | Decoration category for git log --decorate colouring (color.decorate.*). | [API](https://docs.rs/grit-lib/latest/grit_lib/porcelain/log/enum.DecorationKind.html) |
| `grit_lib::porcelain::merge` | module | git merge index/head algorithm core. | [API](https://docs.rs/grit-lib/latest/grit_lib/porcelain/merge/index.html) |
| `grit_lib::porcelain::rebase` | module | git rebase todo-list model and squash/fixup message assembly. | [API](https://docs.rs/grit-lib/latest/grit_lib/porcelain/rebase/index.html) |
| `grit_lib::porcelain::rebase::FixupMessageMode` | enum | Whether a fixup -C/fixup -c step uses the replaced commit message verbatim or opens an editor to amend it. | [API](https://docs.rs/grit-lib/latest/grit_lib/porcelain/rebase/enum.FixupMessageMode.html) |
| `grit_lib::porcelain::rebase::RebaseTodoCmd` | enum | A linear interactive-rebase todo command keyword. | [API](https://docs.rs/grit-lib/latest/grit_lib/porcelain/rebase/enum.RebaseTodoCmd.html) |
| `grit_lib::porcelain::restore` | module | Restore working tree and/or index paths from the index, HEAD, or another tree (git restore semantics). | [API](https://docs.rs/grit-lib/latest/grit_lib/porcelain/restore/index.html) |
| `grit_lib::porcelain::restore::RestoreOptions` | struct | Options for restore_paths, translated from the grit restore CLI. | [API](https://docs.rs/grit-lib/latest/grit_lib/porcelain/restore/struct.RestoreOptions.html) |
| `grit_lib::porcelain::restore::RestoreOutcome` | struct | Outcome of a restore operation: paths written and paths removed in each target. | [API](https://docs.rs/grit-lib/latest/grit_lib/porcelain/restore/struct.RestoreOutcome.html) |
| `grit_lib::porcelain::restore::RestoreSource` | enum | Where explicit --source content comes from; default targets use the index or HEAD. | [API](https://docs.rs/grit-lib/latest/grit_lib/porcelain/restore/enum.RestoreSource.html) |
| `grit_lib::porcelain::revert` | module | git revert pick-engine core. | [API](https://docs.rs/grit-lib/latest/grit_lib/porcelain/revert/index.html) |
| `grit_lib::porcelain::stage_tracked` | module | Stage modifications and deletions of already-tracked paths (git commit -a / -a staging). | [API](https://docs.rs/grit-lib/latest/grit_lib/porcelain/stage_tracked/index.html) |
| `grit_lib::porcelain::stage_tracked::StageTrackedSummary` | struct | Summary of paths updated while staging tracked modifications/deletions. | [API](https://docs.rs/grit-lib/latest/grit_lib/porcelain/stage_tracked/struct.StageTrackedSummary.html) |
| `grit_lib::porcelain::staging` | module | Stage worktree changes into the index (grit add / commit -a engine). | [API](https://docs.rs/grit-lib/latest/grit_lib/porcelain/staging/index.html) |
| `grit_lib::porcelain::stash` | module | git stash apply core, plus the tree-flattening and worktree-mutation primitives the stash engine is built on. | [API](https://docs.rs/grit-lib/latest/grit_lib/porcelain/stash/index.html) |
| `grit_lib::porcelain::stash::FlatTreeEntry` | struct | A single blob entry from a recursively flattened tree. | [API](https://docs.rs/grit-lib/latest/grit_lib/porcelain/stash/struct.FlatTreeEntry.html) |
| `grit_lib::porcelain::status` | module | git status as a structured operation. | [API](https://docs.rs/grit-lib/latest/grit_lib/porcelain/status/index.html) |
| `grit_lib::porcelain::status::IgnoredMode` | enum | How ignored files are reported (git status --ignored[=<mode>]). | [API](https://docs.rs/grit-lib/latest/grit_lib/porcelain/status/enum.IgnoredMode.html) |
| `grit_lib::porcelain::status::RenameDetection` | struct | Rename/copy detection settings for the status diffs (status.renames / --find-renames, status.renameLimit, copy detection). | [API](https://docs.rs/grit-lib/latest/grit_lib/porcelain/status/struct.RenameDetection.html) |
| `grit_lib::porcelain::status::StatusModel` | struct | The computed result of git status: everything the renderers need, with no presentation applied. | [API](https://docs.rs/grit-lib/latest/grit_lib/porcelain/status/struct.StatusModel.html) |
| `grit_lib::porcelain::status::StatusOptions` | struct | Inputs that drive what status computes. | [API](https://docs.rs/grit-lib/latest/grit_lib/porcelain/status/struct.StatusOptions.html) |
| `grit_lib::porcelain::status::UntrackedMode` | enum | How untracked files are reported (git status --untracked-files=<mode>). | [API](https://docs.rs/grit-lib/latest/grit_lib/porcelain/status/enum.UntrackedMode.html) |
| `grit_lib::porcelain::tag` | module | git tag listing/filtering core. | [API](https://docs.rs/grit-lib/latest/grit_lib/porcelain/tag/index.html) |
| `grit_lib::porcelain::worktree_guard` | module | Lightweight worktree cleanliness checks without a full status pass. | [API](https://docs.rs/grit-lib/latest/grit_lib/porcelain/worktree_guard/index.html) |
| `grit_lib::porcelain::worktree_guard::TreeSwitchPlan` | struct | Inputs for a branch switch or fast-forward checkout after cleanliness checks. | [API](https://docs.rs/grit-lib/latest/grit_lib/porcelain/worktree_guard/struct.TreeSwitchPlan.html) |
| `grit_lib::porcelain::worktree_guard::WorktreeSnapshot` | struct | Loaded index and HEAD tree for worktree mutation guards. | [API](https://docs.rs/grit-lib/latest/grit_lib/porcelain/worktree_guard/struct.WorktreeSnapshot.html) |
| `grit_lib::precompose_config` | module | Read core.precomposeunicode without opening a full Repository. | [API](https://docs.rs/grit-lib/latest/grit_lib/precompose_config/index.html) |
| `grit_lib::prelude` | module | The types most callers need, re-exported for use grit_lib::prelude::*;. | [API](https://docs.rs/grit-lib/latest/grit_lib/prelude/index.html) |
| `grit_lib::progress` | module | Progress reporting and cancellation across the library/CLI boundary. | [API](https://docs.rs/grit-lib/latest/grit_lib/progress/index.html) |
| `grit_lib::progress::Cancel` | trait | A cancellation signal checked by long-running library operations at loop boundaries. | [API](https://docs.rs/grit-lib/latest/grit_lib/progress/trait.Cancel.html) |
| `grit_lib::progress::NeverCancel` | struct | A Cancel that never signals cancellation. | [API](https://docs.rs/grit-lib/latest/grit_lib/progress/struct.NeverCancel.html) |
| `grit_lib::progress::NullProgress` | struct | A ProgressSink that discards every update. | [API](https://docs.rs/grit-lib/latest/grit_lib/progress/struct.NullProgress.html) |
| `grit_lib::progress::ProgressSink` | trait | A sink for progress updates emitted by a library operation. | [API](https://docs.rs/grit-lib/latest/grit_lib/progress/trait.ProgressSink.html) |
| `grit_lib::promisor` | module | Partial-clone promisor bookkeeping used by Grit. | [API](https://docs.rs/grit-lib/latest/grit_lib/promisor/index.html) |
| `grit_lib::promisor_remote` | module | The “promisor-remote” protocol v2 capability (see gitprotocol-v2(5) and Documentation/config/promisor.adoc). | [API](https://docs.rs/grit-lib/latest/grit_lib/promisor_remote/index.html) |
| `grit_lib::promisor_remote::PromisorInfo` | struct | One advertised or configured promisor remote. | [API](https://docs.rs/grit-lib/latest/grit_lib/promisor_remote/struct.PromisorInfo.html) |
| `grit_lib::promisor_remote::PromisorReply` | struct | The client’s reply to the server’s promisor-remote advertisement. | [API](https://docs.rs/grit-lib/latest/grit_lib/promisor_remote/struct.PromisorReply.html) |
| `grit_lib::protocol` | module | Protocol allow/deny policy and client wire-protocol version selection. | [API](https://docs.rs/grit-lib/latest/grit_lib/protocol/index.html) |
| `grit_lib::protocol::ClientProtocolVersionInputs` | struct | Explicit inputs for selecting the client-side Git wire protocol version. | [API](https://docs.rs/grit-lib/latest/grit_lib/protocol/struct.ClientProtocolVersionInputs.html) |
| `grit_lib::protocol::ProtocolError` | enum | Errors returned when a transport protocol is not allowed. | [API](https://docs.rs/grit-lib/latest/grit_lib/protocol/enum.ProtocolError.html) |
| `grit_lib::protocol::ProtocolPolicyInputs` | struct | Explicit inputs for protocol allow/deny evaluation. | [API](https://docs.rs/grit-lib/latest/grit_lib/protocol/struct.ProtocolPolicyInputs.html) |
| `grit_lib::protocol_v2` | module | Pure protocol-v2 capability parsing and request-fragment building. | [API](https://docs.rs/grit-lib/latest/grit_lib/protocol_v2/index.html) |
| `grit_lib::protocol_v2::FetchResponseSection` | enum | A section header in a protocol-v2 command=fetch response. | [API](https://docs.rs/grit-lib/latest/grit_lib/protocol_v2/enum.FetchResponseSection.html) |
| `grit_lib::prune_packed` | module | Library implementation of prune-packed. | [API](https://docs.rs/grit-lib/latest/grit_lib/prune_packed/index.html) |
| `grit_lib::prune_packed::PrunePackedOptions` | struct | Options controlling the behaviour of prune_packed_objects. | [API](https://docs.rs/grit-lib/latest/grit_lib/prune_packed/struct.PrunePackedOptions.html) |
| `grit_lib::push` | module | Wire-protocol push orchestration over a crate::transport::Connection. | [API](https://docs.rs/grit-lib/latest/grit_lib/push/index.html) |
| `grit_lib::push_cert` | module | Signed-push certificate generation and verification. | [API](https://docs.rs/grit-lib/latest/grit_lib/push_cert/index.html) |
| `grit_lib::push_cert::CertRefUpdate` | struct | A single ref update line in a push certificate. | [API](https://docs.rs/grit-lib/latest/grit_lib/push_cert/struct.CertRefUpdate.html) |
| `grit_lib::push_cert::PushCertEnv` | struct | The hook-visible certificate environment, mirroring receive-pack’s GIT_PUSH_CERT* variables. | [API](https://docs.rs/grit-lib/latest/grit_lib/push_cert/struct.PushCertEnv.html) |
| `grit_lib::push_report` | module | Push status reporting that matches Git’s output. | [API](https://docs.rs/grit-lib/latest/grit_lib/push_report/index.html) |
| `grit_lib::push_report::PushRefResult` | struct | One reference’s resolved push result, ready for display. | [API](https://docs.rs/grit-lib/latest/grit_lib/push_report/struct.PushRefResult.html) |
| `grit_lib::push_report::PushRefStatus` | enum | The resolved outcome of a single reference update during a push. | [API](https://docs.rs/grit-lib/latest/grit_lib/push_report/enum.PushRefStatus.html) |
| `grit_lib::push_report::PushStatusOutput` | struct | Output produced by format_push_status. | [API](https://docs.rs/grit-lib/latest/grit_lib/push_report/struct.PushStatusOutput.html) |
| `grit_lib::push_submodules` | module | Submodule recursion for git push (--recurse-submodules). | [API](https://docs.rs/grit-lib/latest/grit_lib/push_submodules/index.html) |
| `grit_lib::push_submodules::PushRecurseSubmodules` | enum | How git push should recurse into submodules. | [API](https://docs.rs/grit-lib/latest/grit_lib/push_submodules/enum.PushRecurseSubmodules.html) |
| `grit_lib::quote_path` | module | C-style path quoting compatible with Git’s quote.c / core.quotepath. | [API](https://docs.rs/grit-lib/latest/grit_lib/quote_path/index.html) |
| `grit_lib::receive_pack` | module | Receive-pack configuration and pack-header helpers. | [API](https://docs.rs/grit-lib/latest/grit_lib/receive_pack/index.html) |
| `grit_lib::receive_quarantine` | module | Temporary object directories for receive-pack (Git quarantine). | [API](https://docs.rs/grit-lib/latest/grit_lib/receive_quarantine/index.html) |
| `grit_lib::receive_quarantine::ReceiveQuarantine` | struct | A receive-pack quarantine directory under the repository’s objects/. | [API](https://docs.rs/grit-lib/latest/grit_lib/receive_quarantine/struct.ReceiveQuarantine.html) |
| `grit_lib::ref_exclusions` | module | Reference exclusion rules for rev-list / rev-parse (--exclude, --exclude-hidden). | [API](https://docs.rs/grit-lib/latest/grit_lib/ref_exclusions/index.html) |
| `grit_lib::ref_exclusions::RefExclusions` | struct | Patterns that exclude refs from --all / glob expansion, including hidden-ref config. | [API](https://docs.rs/grit-lib/latest/grit_lib/ref_exclusions/struct.RefExclusions.html) |
| `grit_lib::ref_namespace` | module | Git GIT_NAMESPACE handling: map logical ref names to storage under refs/namespaces/.../. | [API](https://docs.rs/grit-lib/latest/grit_lib/ref_namespace/index.html) |
| `grit_lib::ref_storage` | module | Typed ref storage backend selection (files vs reftable). | [API](https://docs.rs/grit-lib/latest/grit_lib/ref_storage/index.html) |
| `grit_lib::ref_storage::RefStorageFormat` | enum | On-disk ref storage backend named by extensions.refStorage. | [API](https://docs.rs/grit-lib/latest/grit_lib/ref_storage/enum.RefStorageFormat.html) |
| `grit_lib::references` | module | References: the refs backends, reflog, refspecs, name validation, namespaces. | [API](https://docs.rs/grit-lib/latest/grit_lib/references/index.html) |
| `grit_lib::reflog` | module | Reflog reading and management. | [API](https://docs.rs/grit-lib/latest/grit_lib/reflog/index.html) |
| `grit_lib::reflog::GcReflogExpireConfig` | struct | Per-ref gc.<pattern>.reflogExpire* rules plus global gc.reflogExpire / gc.reflogExpireUnreachable. | [API](https://docs.rs/grit-lib/latest/grit_lib/reflog/struct.GcReflogExpireConfig.html) |
| `grit_lib::reflog::GcReflogPattern` | struct | Per-ref gc.<pattern>.reflogExpire* rule from config. | [API](https://docs.rs/grit-lib/latest/grit_lib/reflog/struct.GcReflogPattern.html) |
| `grit_lib::reflog::ReflogEntry` | struct | A single reflog entry. | [API](https://docs.rs/grit-lib/latest/grit_lib/reflog/struct.ReflogEntry.html) |
| `grit_lib::reflog::ReflogExpireAction` | struct | Per-entry report from expire_reflog_git. | [API](https://docs.rs/grit-lib/latest/grit_lib/reflog/struct.ReflogExpireAction.html) |
| `grit_lib::reflog::ReflogExpireActionKind` | enum | What happened to one reflog entry during expire_reflog_git. | [API](https://docs.rs/grit-lib/latest/grit_lib/reflog/enum.ReflogExpireActionKind.html) |
| `grit_lib::reflog::ReflogExpireParams` | struct | Options for expire_reflog_git. | [API](https://docs.rs/grit-lib/latest/grit_lib/reflog/struct.ReflogExpireParams.html) |
| `grit_lib::reflog::ReflogExpireResult` | struct | Result of expire_reflog_git: prune count plus a per-entry action list. | [API](https://docs.rs/grit-lib/latest/grit_lib/reflog/struct.ReflogExpireResult.html) |
| `grit_lib::refs` | module | Reference storage — files backend + reftable backend. | [API](https://docs.rs/grit-lib/latest/grit_lib/refs/index.html) |
| `grit_lib::refs::BranchCommitRefUpdate` | struct | Move a checked-out branch to new_oid and append matching branch and HEAD reflogs. | [API](https://docs.rs/grit-lib/latest/grit_lib/refs/struct.BranchCommitRefUpdate.html) |
| `grit_lib::refs::FilesRefBatchApply` | struct | One create/update/delete applied by apply_files_ref_batch. | [API](https://docs.rs/grit-lib/latest/grit_lib/refs/struct.FilesRefBatchApply.html) |
| `grit_lib::refs::LogRefsConfig` | enum | Core logAllRefUpdates modes (after config lookup), matching Git’s log_refs_config. | [API](https://docs.rs/grit-lib/latest/grit_lib/refs/enum.LogRefsConfig.html) |
| `grit_lib::refs::PackedRefs` | struct | A one-time, in-memory snapshot of a ref store’s packed-refs file. | [API](https://docs.rs/grit-lib/latest/grit_lib/refs/struct.PackedRefs.html) |
| `grit_lib::refs::RawRefLookup` | enum | Outcome of a single storage-level ref lookup (Git refs_read_raw_ref style). | [API](https://docs.rs/grit-lib/latest/grit_lib/refs/enum.RawRefLookup.html) |
| `grit_lib::refs::Ref` | enum | A symbolic or direct reference. | [API](https://docs.rs/grit-lib/latest/grit_lib/refs/enum.Ref.html) |
| `grit_lib::refs::RefBatchItem` | struct | One ref create/update/delete in a batch transaction (see crate::gc::update_refs). | [API](https://docs.rs/grit-lib/latest/grit_lib/refs/struct.RefBatchItem.html) |
| `grit_lib::refs::RefnameUnavailable` | enum | Why a reference name cannot be created (Git refs_verify_refname_available style). | [API](https://docs.rs/grit-lib/latest/grit_lib/refs/enum.RefnameUnavailable.html) |
| `grit_lib::refs::store` | module | Pluggable reference storage: typed transactions and backends. | [API](https://docs.rs/grit-lib/latest/grit_lib/refs/store/index.html) |
| `grit_lib::refs::store::Expected` | enum | Compare-and-swap expectation for a single ref update. | [API](https://docs.rs/grit-lib/latest/grit_lib/refs/store/enum.Expected.html) |
| `grit_lib::refs::store::FilesRefStore` | struct | Loose + packed ref storage on disk. | [API](https://docs.rs/grit-lib/latest/grit_lib/refs/store/struct.FilesRefStore.html) |
| `grit_lib::refs::store::FilesRefStoreConfig` | struct | Explicit context for a files ref store (no environment reads for namespace). | [API](https://docs.rs/grit-lib/latest/grit_lib/refs/store/struct.FilesRefStoreConfig.html) |
| `grit_lib::refs::store::MemoryRefStore` | struct | Fully in-memory ref database with transactional updates. | [API](https://docs.rs/grit-lib/latest/grit_lib/refs/store/struct.MemoryRefStore.html) |
| `grit_lib::refs::store::PreparedRefTransaction` | trait | Committable ref update batch returned from RefStore::prepare. | [API](https://docs.rs/grit-lib/latest/grit_lib/refs/store/trait.PreparedRefTransaction.html) |
| `grit_lib::refs::store::RawRef` | enum | Storage-level ref value without DWIM or resolution. | [API](https://docs.rs/grit-lib/latest/grit_lib/refs/store/enum.RawRef.html) |
| `grit_lib::refs::store::RefEntry` | struct | One ref returned from iteration, optionally with a peeled object id. | [API](https://docs.rs/grit-lib/latest/grit_lib/refs/store/struct.RefEntry.html) |
| `grit_lib::refs::store::RefStorageFormat` | enum | Which physical backend backs a super::RefStore. | [API](https://docs.rs/grit-lib/latest/grit_lib/refs/store/enum.RefStorageFormat.html) |
| `grit_lib::refs::store::RefStore` | trait | Reference storage backend (loose/packed files, reftable, or in-memory). | [API](https://docs.rs/grit-lib/latest/grit_lib/refs/store/trait.RefStore.html) |
| `grit_lib::refs::store::RefStoreError` | enum | Failure modes for reference store reads and transactions. | [API](https://docs.rs/grit-lib/latest/grit_lib/refs/store/enum.RefStoreError.html) |
| `grit_lib::refs::store::RefTransaction` | struct | Batch of ref updates prepared for super::RefStore::prepare. | [API](https://docs.rs/grit-lib/latest/grit_lib/refs/store/struct.RefTransaction.html) |
| `grit_lib::refs::store::RefUpdate` | struct | One ref create, update, delete, or reflog-only touch in a transaction. | [API](https://docs.rs/grit-lib/latest/grit_lib/refs/store/struct.RefUpdate.html) |
| `grit_lib::refs::store::RefUpdateFlags` | struct | Per-update flags (Git REF_NO_DEREF / REF_LOG_ONLY semantics). | [API](https://docs.rs/grit-lib/latest/grit_lib/refs/store/struct.RefUpdateFlags.html) |
| `grit_lib::refs::store::ReflogUpdate` | struct | Metadata appended to a ref update for the reflog. | [API](https://docs.rs/grit-lib/latest/grit_lib/refs/store/struct.ReflogUpdate.html) |
| `grit_lib::refs::store::ReftableRefStore` | struct | On-disk ref storage using the reftable backend (extensions.refStorage = reftable). | [API](https://docs.rs/grit-lib/latest/grit_lib/refs/store/struct.ReftableRefStore.html) |
| `grit_lib::refs_fsck` | module | Reference database consistency checks for git refs verify and git fsck --references. | [API](https://docs.rs/grit-lib/latest/grit_lib/refs_fsck/index.html) |
| `grit_lib::refs_fsck::RefsFsckIssue` | struct | One diagnostic (use format_refs_fsck_line for Git-compatible output). | [API](https://docs.rs/grit-lib/latest/grit_lib/refs_fsck/struct.RefsFsckIssue.html) |
| `grit_lib::refs_fsck::RefsFsckSeverity` | enum | Severity of a refs-fsck diagnostic. | [API](https://docs.rs/grit-lib/latest/grit_lib/refs_fsck/enum.RefsFsckSeverity.html) |
| `grit_lib::refspec` | module | Refspec parsing and validation — a port of git/refspec.c. | [API](https://docs.rs/grit-lib/latest/grit_lib/refspec/index.html) |
| `grit_lib::refspec::RefspecError` | enum | Error returned when a refspec cannot be parsed. | [API](https://docs.rs/grit-lib/latest/grit_lib/refspec/enum.RefspecError.html) |
| `grit_lib::refspec::RefspecItem` | struct | A parsed refspec item. | [API](https://docs.rs/grit-lib/latest/grit_lib/refspec/struct.RefspecItem.html) |
| `grit_lib::reftable` | module | Reftable format — binary reference storage. | [API](https://docs.rs/grit-lib/latest/grit_lib/reftable/index.html) |
| `grit_lib::reftable::LogRecord` | struct | A decoded log record. | [API](https://docs.rs/grit-lib/latest/grit_lib/reftable/struct.LogRecord.html) |
| `grit_lib::reftable::RefRecord` | struct | A decoded ref record. | [API](https://docs.rs/grit-lib/latest/grit_lib/reftable/struct.RefRecord.html) |
| `grit_lib::reftable::RefValue` | enum | A single reference record as stored in a reftable. | [API](https://docs.rs/grit-lib/latest/grit_lib/reftable/enum.RefValue.html) |
| `grit_lib::reftable::ReftableReader` | struct | Reads a single reftable file from a byte buffer. | [API](https://docs.rs/grit-lib/latest/grit_lib/reftable/struct.ReftableReader.html) |
| `grit_lib::reftable::ReftableStack` | struct | Manages the $GIT_DIR/reftable/ directory and tables.list stack. | [API](https://docs.rs/grit-lib/latest/grit_lib/reftable/struct.ReftableStack.html) |
| `grit_lib::reftable::ReftableTransactionUpdate` | struct | A ref update that should be written to a reftable transaction. | [API](https://docs.rs/grit-lib/latest/grit_lib/reftable/struct.ReftableTransactionUpdate.html) |
| `grit_lib::reftable::ReftableWriter` | struct | Writes a single reftable file. | [API](https://docs.rs/grit-lib/latest/grit_lib/reftable/struct.ReftableWriter.html) |
| `grit_lib::reftable::WriteOptions` | struct | Write options for reftable creation. | [API](https://docs.rs/grit-lib/latest/grit_lib/reftable/struct.WriteOptions.html) |
| `grit_lib::remote` | module | Unified remote URL typing and transport dispatch for fetch, push, and ref listing. | [API](https://docs.rs/grit-lib/latest/grit_lib/remote/index.html) |
| `grit_lib::remote::HttpClientFactory` | trait | Builds HTTP clients for smart-HTTP remotes. | [API](https://docs.rs/grit-lib/latest/grit_lib/remote/trait.HttpClientFactory.html) |
| `grit_lib::remote::ListRefsOptions` | struct | Options controlling Remote::list_refs output, aligned with git ls-remote. | [API](https://docs.rs/grit-lib/latest/grit_lib/remote/struct.ListRefsOptions.html) |
| `grit_lib::remote::Remote` | struct | A resolved remote: name (if from config), URL(s), and fetch refspecs. | [API](https://docs.rs/grit-lib/latest/grit_lib/remote/struct.Remote.html) |
| `grit_lib::remote::RemoteError` | enum | Errors specific to remote URL resolution and dispatch. | [API](https://docs.rs/grit-lib/latest/grit_lib/remote/enum.RemoteError.html) |
| `grit_lib::remote::RemoteRef` | struct | A single reference returned by Remote::list_refs. | [API](https://docs.rs/grit-lib/latest/grit_lib/remote/struct.RemoteRef.html) |
| `grit_lib::remote::RemoteUrl` | enum | A parsed remote URL by transport kind. | [API](https://docs.rs/grit-lib/latest/grit_lib/remote/enum.RemoteUrl.html) |
| `grit_lib::repo` | module | Repository discovery and the primary Repository handle. | [API](https://docs.rs/grit-lib/latest/grit_lib/repo/index.html) |
| `grit_lib::repo::Repository` | struct | A handle to an open Git repository. | [API](https://docs.rs/grit-lib/latest/grit_lib/repo/struct.Repository.html) |
| `grit_lib::repo_caches` | module | Repository-scoped caches shared by an open Repository. | [API](https://docs.rs/grit-lib/latest/grit_lib/repo_caches/index.html) |
| `grit_lib::repo_caches::RepoCaches` | struct | Per-repository cache arena (held behind Arc on Repository). | [API](https://docs.rs/grit-lib/latest/grit_lib/repo_caches/struct.RepoCaches.html) |
| `grit_lib::rerere` | module | Git-compatible rerere (MERGE_RR, rr-cache/, conflict ID hashing). | [API](https://docs.rs/grit-lib/latest/grit_lib/rerere/index.html) |
| `grit_lib::rerere::RerereAutoupdate` | enum | Outcome of rerere handling one path (replaces stderr status lines). | [API](https://docs.rs/grit-lib/latest/grit_lib/rerere/enum.RerereAutoupdate.html) |
| `grit_lib::rerere::RerereEvent` | struct | One rerere status event for a path. | [API](https://docs.rs/grit-lib/latest/grit_lib/rerere/struct.RerereEvent.html) |
| `grit_lib::resolve_undo` | module | Git index REUC (resolve-undo) extension — records unmerged stages when a conflict is resolved. | [API](https://docs.rs/grit-lib/latest/grit_lib/resolve_undo/index.html) |
| `grit_lib::resolve_undo::ResolveUndoRecord` | struct | Per-path undo data: up to three conflict stages (index 0 = stage 1). | [API](https://docs.rs/grit-lib/latest/grit_lib/resolve_undo/struct.ResolveUndoRecord.html) |
| `grit_lib::rev_list` | module | Commit traversal and output planning for rev-list. | [API](https://docs.rs/grit-lib/latest/grit_lib/rev_list/index.html) |
| `grit_lib::rev_list::BisectEntry` | struct | Per-commit bisection score for rev-list --bisect* output. | [API](https://docs.rs/grit-lib/latest/grit_lib/rev_list/struct.BisectEntry.html) |
| `grit_lib::rev_list::BisectSelection` | struct | Bisection analysis result for a selected revision set. | [API](https://docs.rs/grit-lib/latest/grit_lib/rev_list/struct.BisectSelection.html) |
| `grit_lib::rev_list::FilterObjectKind` | enum | Kind selector for object:type=<kind> filters. | [API](https://docs.rs/grit-lib/latest/grit_lib/rev_list/enum.FilterObjectKind.html) |
| `grit_lib::rev_list::MissingAction` | enum | Behavior when reachable objects are missing. | [API](https://docs.rs/grit-lib/latest/grit_lib/rev_list/enum.MissingAction.html) |
| `grit_lib::rev_list::ObjectFilter` | enum | Object filter specification for --filter=. | [API](https://docs.rs/grit-lib/latest/grit_lib/rev_list/enum.ObjectFilter.html) |
| `grit_lib::rev_list::ObjectWalkRoot` | struct | Non-commit root from revision arguments (tag, rev:path, raw tree/blob OID), for object walks. | [API](https://docs.rs/grit-lib/latest/grit_lib/rev_list/struct.ObjectWalkRoot.html) |
| `grit_lib::rev_list::OrderingMode` | enum | Ordering mode for commit output. | [API](https://docs.rs/grit-lib/latest/grit_lib/rev_list/enum.OrderingMode.html) |
| `grit_lib::rev_list::OutputMode` | enum | User-facing output mode for rev-list. | [API](https://docs.rs/grit-lib/latest/grit_lib/rev_list/enum.OutputMode.html) |
| `grit_lib::rev_list::RevListOptions` | struct | Parsed and normalized options for rev-list traversal. | [API](https://docs.rs/grit-lib/latest/grit_lib/rev_list/struct.RevListOptions.html) |
| `grit_lib::rev_list::RevListResult` | struct | Final commit selection result. | [API](https://docs.rs/grit-lib/latest/grit_lib/rev_list/struct.RevListResult.html) |
| `grit_lib::rev_list_error` | module | Typed failures from crate::rev_list. | [API](https://docs.rs/grit-lib/latest/grit_lib/rev_list_error/index.html) |
| `grit_lib::rev_list_error::RevListError` | enum | Failure modes when walking revisions or parsing rev-list options. | [API](https://docs.rs/grit-lib/latest/grit_lib/rev_list_error/enum.RevListError.html) |
| `grit_lib::rev_parse` | module | Revision parsing and repository discovery helpers for rev-parse. | [API](https://docs.rs/grit-lib/latest/grit_lib/rev_parse/index.html) |
| `grit_lib::rev_parse::IndexColonSpec` | struct | Parsed :path / :N:path index revision syntax (leading colon, not :/search). | [API](https://docs.rs/grit-lib/latest/grit_lib/rev_parse/struct.IndexColonSpec.html) |
| `grit_lib::rev_parse::IndexPathEntry` | struct | One index entry resolved from a :path / :N:path revision string. | [API](https://docs.rs/grit-lib/latest/grit_lib/rev_parse/struct.IndexPathEntry.html) |
| `grit_lib::rev_parse::TreeishBlobAtPath` | struct | Resolved blob (non-tree) at treeish:path for diff plumbing. | [API](https://docs.rs/grit-lib/latest/grit_lib/rev_parse/struct.TreeishBlobAtPath.html) |
| `grit_lib::rev_parse_error` | module | Typed failures from revision parsing (crate::rev_parse). | [API](https://docs.rs/grit-lib/latest/grit_lib/rev_parse_error/index.html) |
| `grit_lib::rev_parse_error::AmbiguousObjectHint` | struct | One candidate line when a short object id is ambiguous. | [API](https://docs.rs/grit-lib/latest/grit_lib/rev_parse_error/struct.AmbiguousObjectHint.html) |
| `grit_lib::rev_parse_error::RevParseError` | enum | Failure modes when resolving revision specs, upstream/push refs, paths, and reflogs. | [API](https://docs.rs/grit-lib/latest/grit_lib/rev_parse_error/enum.RevParseError.html) |
| `grit_lib::revision` | module | Revision machinery: rev-parse, rev-list, name-rev, commit-graph. | [API](https://docs.rs/grit-lib/latest/grit_lib/revision/index.html) |
| `grit_lib::serve` | module | Server side of the Git wire protocol: answering fetches and accepting pushes. | [API](https://docs.rs/grit-lib/latest/grit_lib/serve/index.html) |
| `grit_lib::serve::HookRunRecord` | struct | One server-side hook invocation during receive-pack. | [API](https://docs.rs/grit-lib/latest/grit_lib/serve/struct.HookRunRecord.html) |
| `grit_lib::serve::ProtocolVersion` | enum | Wire protocol version requested by the client. | [API](https://docs.rs/grit-lib/latest/grit_lib/serve/enum.ProtocolVersion.html) |
| `grit_lib::serve::ReceiveOutcome` | struct | What a push session did. | [API](https://docs.rs/grit-lib/latest/grit_lib/serve/struct.ReceiveOutcome.html) |
| `grit_lib::serve::ReceivePolicy` | struct | Which ref updates the server refuses. | [API](https://docs.rs/grit-lib/latest/grit_lib/serve/struct.ReceivePolicy.html) |
| `grit_lib::serve::RefUpdateResult` | struct | The result of one requested ref update. | [API](https://docs.rs/grit-lib/latest/grit_lib/serve/struct.RefUpdateResult.html) |
| `grit_lib::serve::ServeError` | enum | Errors produced while serving a fetch or a push. | [API](https://docs.rs/grit-lib/latest/grit_lib/serve/enum.ServeError.html) |
| `grit_lib::serve::ServeOptions` | struct | How a serving session is framed on the wire. | [API](https://docs.rs/grit-lib/latest/grit_lib/serve/struct.ServeOptions.html) |
| `grit_lib::shallow` | module | Shallow repository metadata (.git/shallow). | [API](https://docs.rs/grit-lib/latest/grit_lib/shallow/index.html) |
| `grit_lib::shared_repo` | module | Shared-repository permission helpers (core.sharedRepository, --shared). | [API](https://docs.rs/grit-lib/latest/grit_lib/shared_repo/index.html) |
| `grit_lib::signing` | module | Commit/tag GPG (and gpgsm/ssh) signing and signature verification. | [API](https://docs.rs/grit-lib/latest/grit_lib/signing/index.html) |
| `grit_lib::signing::GpgConfig` | struct | Resolved signing/verification configuration. | [API](https://docs.rs/grit-lib/latest/grit_lib/signing/struct.GpgConfig.html) |
| `grit_lib::signing::GpgFormat` | enum | The signature format selected via gpg.format. | [API](https://docs.rs/grit-lib/latest/grit_lib/signing/enum.GpgFormat.html) |
| `grit_lib::signing::SignatureCheck` | struct | A parsed signature check result. | [API](https://docs.rs/grit-lib/latest/grit_lib/signing/struct.SignatureCheck.html) |
| `grit_lib::signing::TrustLevel` | enum | Signature trust level, as reported for a verified signature. | [API](https://docs.rs/grit-lib/latest/grit_lib/signing/enum.TrustLevel.html) |
| `grit_lib::sparse_checkout` | module | Sparse-checkout pattern parsing and path membership (cone and non-cone). | [API](https://docs.rs/grit-lib/latest/grit_lib/sparse_checkout/index.html) |
| `grit_lib::sparse_checkout::ConePatterns` | struct | Cone-mode sparse state: keys use a leading / (Git’s internal form). | [API](https://docs.rs/grit-lib/latest/grit_lib/sparse_checkout/struct.ConePatterns.html) |
| `grit_lib::sparse_checkout::ConeWorkspace` | struct | Mutable cone sparse state (Git pattern_list hashmaps) for building sparse-checkout files. | [API](https://docs.rs/grit-lib/latest/grit_lib/sparse_checkout/struct.ConeWorkspace.html) |
| `grit_lib::sparse_checkout::NonConePatterns` | struct | Parsed non-cone sparse-checkout patterns in file order (last match wins). | [API](https://docs.rs/grit-lib/latest/grit_lib/sparse_checkout/struct.NonConePatterns.html) |
| `grit_lib::split_index` | module | Split index: link extension and sharedindex.<sha1> (Git split-index.c). | [API](https://docs.rs/grit-lib/latest/grit_lib/split_index/index.html) |
| `grit_lib::split_index::WriteSplitIndexRequest` | struct | Request from update-index for the next index write. | [API](https://docs.rs/grit-lib/latest/grit_lib/split_index/struct.WriteSplitIndexRequest.html) |
| `grit_lib::state` | module | Repository state machine — HEAD resolution, branch status, and in-progress operation detection. | [API](https://docs.rs/grit-lib/latest/grit_lib/state/index.html) |
| `grit_lib::state::HeadState` | enum | The current state of HEAD. | [API](https://docs.rs/grit-lib/latest/grit_lib/state/enum.HeadState.html) |
| `grit_lib::state::InProgressOperation` | enum | An in-progress operation that the repository is in the middle of. | [API](https://docs.rs/grit-lib/latest/grit_lib/state/enum.InProgressOperation.html) |
| `grit_lib::state::RepoState` | struct | Full snapshot of a repository’s state. | [API](https://docs.rs/grit-lib/latest/grit_lib/state/struct.RepoState.html) |
| `grit_lib::state::WtStatusState` | struct | Snapshot of repository state used by git status long-format output (wt-status.c). | [API](https://docs.rs/grit-lib/latest/grit_lib/state/struct.WtStatusState.html) |
| `grit_lib::stripspace` | module | Core logic for git stripspace. | [API](https://docs.rs/grit-lib/latest/grit_lib/stripspace/index.html) |
| `grit_lib::stripspace::Mode` | enum | Processing mode for process. | [API](https://docs.rs/grit-lib/latest/grit_lib/stripspace/enum.Mode.html) |
| `grit_lib::submodule_active` | module | Submodule “active” state (submodule.c is_submodule_active parity). | [API](https://docs.rs/grit-lib/latest/grit_lib/submodule_active/index.html) |
| `grit_lib::submodule_config` | module | Submodule registration and activation (Git submodule.c parity for tooling). | [API](https://docs.rs/grit-lib/latest/grit_lib/submodule_config/index.html) |
| `grit_lib::submodule_config::SubmoduleRegistration` | struct | Maps a submodule work tree path (as in the index / .gitmodules) to its submodule section name. | [API](https://docs.rs/grit-lib/latest/grit_lib/submodule_config/struct.SubmoduleRegistration.html) |
| `grit_lib::submodule_config_cache` | module | Submodule configuration cache (Git submodule-config.c subset for test-tool). | [API](https://docs.rs/grit-lib/latest/grit_lib/submodule_config_cache/index.html) |
| `grit_lib::submodule_config_cache::SubmoduleConfigCache` | struct | Cache of parsed .gitmodules blobs (by blob OID) plus path/name indexes. | [API](https://docs.rs/grit-lib/latest/grit_lib/submodule_config_cache/struct.SubmoduleConfigCache.html) |
| `grit_lib::submodule_config_cache::SubmoduleInfo` | struct | Resolved submodule identity for test output (Submodule name: 'x' for path 'y'). | [API](https://docs.rs/grit-lib/latest/grit_lib/submodule_config_cache/struct.SubmoduleInfo.html) |
| `grit_lib::submodule_gitdir` | module | Submodule gitdir paths when extensions.submodulePathConfig is enabled. | [API](https://docs.rs/grit-lib/latest/grit_lib/submodule_gitdir/index.html) |
| `grit_lib::terminal` | module | Cross-platform terminal capability detection for ANSI color output. | [API](https://docs.rs/grit-lib/latest/grit_lib/terminal/index.html) |
| `grit_lib::textconv_cache` | module | Git-compatible diff.<driver>.cachetextconv storage under refs/notes/textconv/<driver>. | [API](https://docs.rs/grit-lib/latest/grit_lib/textconv_cache/index.html) |
| `grit_lib::transfer` | module | Embedder-facing transfer (fetch / push) result & option types, plus the negotiation-driven pack builder. | [API](https://docs.rs/grit-lib/latest/grit_lib/transfer/index.html) |
| `grit_lib::transfer::FetchOptions` | struct | Options controlling a fetch. | [API](https://docs.rs/grit-lib/latest/grit_lib/transfer/struct.FetchOptions.html) |
| `grit_lib::transfer::FetchOutcome` | struct | The structured result of a fetch, ready for the embedder’s ref-store apply. | [API](https://docs.rs/grit-lib/latest/grit_lib/transfer/struct.FetchOutcome.html) |
| `grit_lib::transfer::PushOptions` | struct | Options controlling a push. | [API](https://docs.rs/grit-lib/latest/grit_lib/transfer/struct.PushOptions.html) |
| `grit_lib::transfer::PushOutcome` | struct | The structured result of a push. | [API](https://docs.rs/grit-lib/latest/grit_lib/transfer/struct.PushOutcome.html) |
| `grit_lib::transfer::PushRefSpec` | struct | A single ref update requested by a push. | [API](https://docs.rs/grit-lib/latest/grit_lib/transfer/struct.PushRefSpec.html) |
| `grit_lib::transfer::RefUpdate` | struct | The resolved outcome of one reference during a fetch. | [API](https://docs.rs/grit-lib/latest/grit_lib/transfer/struct.RefUpdate.html) |
| `grit_lib::transfer::TagMode` | enum | Which tags to fetch alongside the requested refs. | [API](https://docs.rs/grit-lib/latest/grit_lib/transfer/enum.TagMode.html) |
| `grit_lib::transfer::UpdateMode` | enum | How a single reference resolved during a fetch (or would resolve in a push). | [API](https://docs.rs/grit-lib/latest/grit_lib/transfer/enum.UpdateMode.html) |
| `grit_lib::transport` | module | Embedder-facing transport abstraction for the Git wire protocols. | [API](https://docs.rs/grit-lib/latest/grit_lib/transport/index.html) |
| `grit_lib::transport::Advertisement` | struct | The captured ref/capability advertisement for a v0/v1 connection. | [API](https://docs.rs/grit-lib/latest/grit_lib/transport/struct.Advertisement.html) |
| `grit_lib::transport::ConnectOptions` | struct | Options controlling the transport handshake. | [API](https://docs.rs/grit-lib/latest/grit_lib/transport/struct.ConnectOptions.html) |
| `grit_lib::transport::Connection` | trait | A live, bidirectional pkt-line connection to a Git service, with the ref/capability advertisement captured during the handshake. | [API](https://docs.rs/grit-lib/latest/grit_lib/transport/trait.Connection.html) |
| `grit_lib::transport::GitDaemonConnection` | struct | A live connection to a Git daemon over a duplex TCP socket. | [API](https://docs.rs/grit-lib/latest/grit_lib/transport/struct.GitDaemonConnection.html) |
| `grit_lib::transport::GitDaemonTransport` | struct | The native git:// daemon transport. | [API](https://docs.rs/grit-lib/latest/grit_lib/transport/struct.GitDaemonTransport.html) |
| `grit_lib::transport::GitDaemonUrl` | struct | Parsed git://host[:port]/path (path includes the leading /). | [API](https://docs.rs/grit-lib/latest/grit_lib/transport/struct.GitDaemonUrl.html) |
| `grit_lib::transport::Service` | enum | The Git service a Connection speaks. | [API](https://docs.rs/grit-lib/latest/grit_lib/transport/enum.Service.html) |
| `grit_lib::transport::SshCommand` | enum | How the SshTransport invokes ssh. | [API](https://docs.rs/grit-lib/latest/grit_lib/transport/enum.SshCommand.html) |
| `grit_lib::transport::SshConnection` | struct | A live connection to a remote Git service over an ssh subprocess. | [API](https://docs.rs/grit-lib/latest/grit_lib/transport/struct.SshConnection.html) |
| `grit_lib::transport::SshTransport` | struct | The ssh transport: spawn ssh [opts] <host> git-upload-pack '<path>' and expose the child’s stdio as a Connection. | [API](https://docs.rs/grit-lib/latest/grit_lib/transport/struct.SshTransport.html) |
| `grit_lib::transport::SshUrl` | struct | A parsed SSH remote (scp-style host:path, ssh://, or git+ssh://). | [API](https://docs.rs/grit-lib/latest/grit_lib/transport/struct.SshUrl.html) |
| `grit_lib::transport::Transport` | trait | A factory that connects to a remote and performs the protocol handshake. | [API](https://docs.rs/grit-lib/latest/grit_lib/transport/trait.Transport.html) |
| `grit_lib::transport::http` | module | Smart-HTTP Git transport over a pluggable HTTP client. | [API](https://docs.rs/grit-lib/latest/grit_lib/transport/http/index.html) |
| `grit_lib::transport::http::HttpClient` | trait | The minimal HTTP surface the smart-HTTP transport needs. | [API](https://docs.rs/grit-lib/latest/grit_lib/transport/http/trait.HttpClient.html) |
| `grit_lib::transport::http::SmartHttpTransport` | struct | A smart-HTTP Transport over a pluggable HttpClient. | [API](https://docs.rs/grit-lib/latest/grit_lib/transport/http/struct.SmartHttpTransport.html) |
| `grit_lib::transport::stateless_http` | module | Smart-HTTP Connection over stateless POST rounds (upload-pack) or a single POST body (receive-pack). | [API](https://docs.rs/grit-lib/latest/grit_lib/transport/stateless_http/index.html) |
| `grit_lib::transport::stateless_http::StatelessHttpConnection` | struct | A live smart-HTTP connection backed by HttpClient stateless RPC. | [API](https://docs.rs/grit-lib/latest/grit_lib/transport/stateless_http/struct.StatelessHttpConnection.html) |
| `grit_lib::transport_path` | module | Safety checks and path resolution for local transport URLs (matches Git connect.c / path.c). | [API](https://docs.rs/grit-lib/latest/grit_lib/transport_path/index.html) |
| `grit_lib::transport_path::NoDirectoryName` | struct | Error returned by git_url_basename when no directory name can be derived from a URL. | [API](https://docs.rs/grit-lib/latest/grit_lib/transport_path/struct.NoDirectoryName.html) |
| `grit_lib::transport_path::TransportPathError` | enum | Errors returned while validating local transport paths. | [API](https://docs.rs/grit-lib/latest/grit_lib/transport_path/enum.TransportPathError.html) |
| `grit_lib::tree_path_follow` | module | Resolve tree paths with symlink following (get_tree_entry_follow_symlinks). | [API](https://docs.rs/grit-lib/latest/grit_lib/tree_path_follow/index.html) |
| `grit_lib::tree_path_follow::FollowPathFailure` | enum | Failure modes reported as special git cat-file --batch-check lines. | [API](https://docs.rs/grit-lib/latest/grit_lib/tree_path_follow/enum.FollowPathFailure.html) |
| `grit_lib::tree_path_follow::FollowPathResult` | enum | Result of resolving tree_oid:path with symlink following. | [API](https://docs.rs/grit-lib/latest/grit_lib/tree_path_follow/enum.FollowPathResult.html) |
| `grit_lib::unicode_normalization` | module | UTF-8 NFC path normalization for macOS-style filesystems (core.precomposeUnicode). | [API](https://docs.rs/grit-lib/latest/grit_lib/unicode_normalization/index.html) |
| `grit_lib::unicode_normalization::WorktreePathForStaging` | struct | Absolute worktree path and repository-relative index spelling after NFC/NFD resolution. | [API](https://docs.rs/grit-lib/latest/grit_lib/unicode_normalization/struct.WorktreePathForStaging.html) |
| `grit_lib::unpack_objects` | module | unpack-objects: unpack a pack stream into loose objects. | [API](https://docs.rs/grit-lib/latest/grit_lib/unpack_objects/index.html) |
| `grit_lib::unpack_objects::PackIndexRecord` | struct | Resolved (oid, pack_offset) pairs for every object slot in a pack byte stream. | [API](https://docs.rs/grit-lib/latest/grit_lib/unpack_objects/struct.PackIndexRecord.html) |
| `grit_lib::unpack_objects::UnpackOptions` | struct | Options controlling unpack-objects behaviour. | [API](https://docs.rs/grit-lib/latest/grit_lib/unpack_objects/struct.UnpackOptions.html) |
| `grit_lib::untracked_cache` | module | Git index UNTR (untracked cache) — git/dir.c / read-cache.c. | [API](https://docs.rs/grit-lib/latest/grit_lib/untracked_cache/index.html) |
| `grit_lib::untracked_cache::OidStat` | struct | Git struct stat_data on disk (36 bytes). | [API](https://docs.rs/grit-lib/latest/grit_lib/untracked_cache/struct.OidStat.html) |
| `grit_lib::untracked_cache::UntrackedCache` | struct | Collect untracked paths from a populated untracked cache tree. | [API](https://docs.rs/grit-lib/latest/grit_lib/untracked_cache/struct.UntrackedCache.html) |
| `grit_lib::upload_filter` | module | Upload-pack object filter policy. | [API](https://docs.rs/grit-lib/latest/grit_lib/upload_filter/index.html) |
| `grit_lib::upload_filter::UploadFilterError` | enum | Error returned when an upload-pack filter request is not allowed by config. | [API](https://docs.rs/grit-lib/latest/grit_lib/upload_filter/enum.UploadFilterError.html) |
| `grit_lib::url_rewrite` | module | URL rewrite helpers for url.*.insteadOf / url.*.pushInsteadOf. | [API](https://docs.rs/grit-lib/latest/grit_lib/url_rewrite/index.html) |
| `grit_lib::userdiff` | module | User-defined and built-in diff function-name matching. | [API](https://docs.rs/grit-lib/latest/grit_lib/userdiff/index.html) |
| `grit_lib::userdiff::FuncnameMatcher` | struct | Compiled function-name matcher used for diff hunk headers. | [API](https://docs.rs/grit-lib/latest/grit_lib/userdiff/struct.FuncnameMatcher.html) |
| `grit_lib::whitespace_rule` | module | Git-compatible core.whitespace rules and ws_fix_copy (git/ws.c). | [API](https://docs.rs/grit-lib/latest/grit_lib/whitespace_rule/index.html) |
| `grit_lib::wildmatch` | module | Git-compatible wildmatch pattern matching. | [API](https://docs.rs/grit-lib/latest/grit_lib/wildmatch/index.html) |
| `grit_lib::worktree` | module | Linked worktree registry: discovery, listing, and admin-dir layout. | [API](https://docs.rs/grit-lib/latest/grit_lib/worktree/index.html) |
| `grit_lib::worktree::WorktreeEntry` | struct | One row returned by list_worktrees. | [API](https://docs.rs/grit-lib/latest/grit_lib/worktree/struct.WorktreeEntry.html) |
| `grit_lib::worktree_cwd` | module | Process current working directory relative to a Git work tree. | [API](https://docs.rs/grit-lib/latest/grit_lib/worktree_cwd/index.html) |
| `grit_lib::worktree_index` | module | Index and working tree: the index, sparse checkout, attributes, ignore, CRLF. | [API](https://docs.rs/grit-lib/latest/grit_lib/worktree_index/index.html) |
| `grit_lib::worktree_ref` | module | Per-worktree ref name parsing and storage location (Git parse_worktree_ref / files_ref_path). | [API](https://docs.rs/grit-lib/latest/grit_lib/worktree_ref/index.html) |
| `grit_lib::worktree_ref::RefWorktreeType` | enum | How a ref name maps to on-disk storage across worktrees. | [API](https://docs.rs/grit-lib/latest/grit_lib/worktree_ref/enum.RefWorktreeType.html) |
| `grit_lib::worktree_rules` | module | Per-operation worktree attribute and ignore context. | [API](https://docs.rs/grit-lib/latest/grit_lib/worktree_rules/index.html) |
| `grit_lib::worktree_rules::WorktreeRules` | struct | Attribute/ignore/conversion state shared across one porcelain operation. | [API](https://docs.rs/grit-lib/latest/grit_lib/worktree_rules/struct.WorktreeRules.html) |
| `grit_lib::write_tree` | module | Build tree objects from index entries (git write-tree core logic). | [API](https://docs.rs/grit-lib/latest/grit_lib/write_tree/index.html) |
| `grit_lib::write_tree::WriteTreeFlags` | struct | Options for cache_tree_update and write_tree_update_index. | [API](https://docs.rs/grit-lib/latest/grit_lib/write_tree/struct.WriteTreeFlags.html) |
| `grit_lib::write_tree::WriteTreePersistence` | enum | How cache_tree_update persists rebuilt tree objects. | [API](https://docs.rs/grit-lib/latest/grit_lib/write_tree/enum.WriteTreePersistence.html) |
| `grit_lib::ws` | module | Git-compatible whitespace rules (core.whitespace, whitespace attribute). | [API](https://docs.rs/grit-lib/latest/grit_lib/ws/index.html) |
| `grit_lib::ws::WhitespaceGitAttr` | enum | Blank lines at end of file (handled at apply layer, not in ws_check). | [API](https://docs.rs/grit-lib/latest/grit_lib/ws/enum.WhitespaceGitAttr.html) |
# https://grit-scm.com/docs/library/bitmaps/index.md
# Reachability bitmaps
> Query pack and MIDX commit bitmaps for fast object reachability and counting.
Git stores optional **reachability bitmaps** alongside pack and multi-pack-index (MIDX) files. grit-lib reads and writes Git-compatible **BITM v1** sidecars (EWAH-compressed sets, XOR commit chains, optional name-hash cache and lookup table). Use them for fast rev-list counting, fetch negotiation, and pack generation without walking the full object graph on every request.
For pack-only write options and on-disk layout details, see the **pack-bitmaps** guide page in this section (`content/docs/library/pack-bitmaps.md`).
## Reading pack and MIDX bitmaps
[`BitmapIndex::open`](https://docs.rs/grit-lib/latest/grit_lib/pack_bitmap/struct.BitmapIndex.html) on a [`Repository`](https://docs.rs/grit-lib/latest/grit_lib/repo/struct.Repository.html) picks the active index: **MIDX bitmap when present**, otherwise the largest pack’s `.bitmap`. It returns `Ok(None)` when no valid sidecar exists (missing file, zero-byte placeholder, or corrupt header).
After open:
- [`BitmapIndex::commit_bitmap`](https://docs.rs/grit-lib/latest/grit_lib/pack_bitmap/struct.BitmapIndex.html) decodes one commit’s reachability set (type-filtered EWAH).
- [`BitmapIndex::oid_at`](https://docs.rs/grit-lib/latest/grit_lib/pack_bitmap/struct.BitmapIndex.html) / [`object_count`](https://docs.rs/grit-lib/latest/grit_lib/pack_bitmap/struct.BitmapIndex.html) map pack positions to object ids.
- Optional [`name_hash`](https://docs.rs/grit-lib/latest/grit_lib/pack_bitmap/struct.BitmapIndex.html) entries come from the name-hash cache (path hashes during tree walks).
- [`has_lookup_table`](https://docs.rs/grit-lib/latest/grit_lib/pack_bitmap/struct.BitmapIndex.html) reports whether a lookup table chunk is present.
Integration tests in `grit-lib/tests/pack_bitmap_read_git_compat.rs` round-trip **git-written** and **grit-written** pack bitmaps and MIDX bitmaps against `git rev-list --test-bitmap`.
## Querying reachability
[`BitmapIndex::reachability`](https://docs.rs/grit-lib/latest/grit_lib/pack_bitmap/struct.BitmapIndex.html) takes a [`ReachabilityQuery`](https://docs.rs/grit-lib/latest/grit_lib/bitmap_walk/struct.ReachabilityQuery.html) (wants, haves, optional [`ObjectFilter`](https://docs.rs/grit-lib/latest/grit_lib/rev_list/enum.ObjectFilter.html)), and [`MissingAction`](https://docs.rs/grit-lib/latest/grit_lib/rev_list/enum.MissingAction.html) for missing links. It returns [`ReachableSet`](https://docs.rs/grit-lib/latest/grit_lib/bitmap_walk/struct.ReachableSet.html) or [`BitmapWalkUnsupported`](https://docs.rs/grit-lib/latest/grit_lib/bitmap_walk/struct.BitmapWalkUnsupported.html) when the repository is shallow or the filter needs a non-bitmap walk (`sparse:oid`, `tree:<n>` with `n > 0`, and similar).
[`ReachableSet`](https://docs.rs/grit-lib/latest/grit_lib/bitmap_walk/struct.ReachableSet.html) exposes `object_ids` for indexed and **extended** (out-of-namespace) objects, and `iter_grouped_by_kind` for oids in Git’s bitmap order (commits, trees, blobs, tags).
[`BitmapIndex::verify_commit`](https://docs.rs/grit-lib/latest/grit_lib/pack_bitmap/struct.BitmapIndex.html) compares a stored commit bitmap with a fresh non-bitmap walk (same idea as `git rev-list --test-bitmap`).
## Writing pack bitmaps
[`PackBitmapWriter`](https://docs.rs/grit-lib/latest/grit_lib/pack_bitmap/struct.PackBitmapWriter.html) and [`Repository::write_pack_bitmap`](https://docs.rs/grit-lib/latest/grit_lib/repo/struct.Repository.html) build a `.bitmap` for an **existing** pack index whose objects are closed under reachability from the repository’s refs (typical after `git repack -ad`). Pass [`PackBitmapWriteOptions`](https://docs.rs/grit-lib/latest/grit_lib/pack_bitmap/struct.PackBitmapWriteOptions.html) explicitly, or use [`ConfigSet::pack_bitmap_write_options`](https://docs.rs/grit-lib/latest/grit_lib/config/struct.ConfigSet.html) for Git’s `pack.writeBitmapHashCache`, `pack.writeBitmapLookupTable`, and `pack.preferBitmapTips`.
If no `.rev` sidecar exists, the writer creates one so object order matches Git’s pack-offset order. Output is deterministic for identical inputs. A pack that is not closed under reachability returns [`PackBitmapWriteError::NotClosed`](https://docs.rs/grit-lib/latest/grit_lib/pack_bitmap/enum.PackBitmapWriteError.html).
## MIDX bitmaps
When grit writes or compacts a multi-pack-index with bitmap support enabled, it emits real MIDX `.bitmap` chunks (and matching `.rev` sidecars) instead of zero-byte placeholders. [`BitmapIndex::open`](https://docs.rs/grit-lib/latest/grit_lib/pack_bitmap/struct.BitmapIndex.html) prefers that MIDX bitmap for reachability queries. See `grit-lib/tests/midx_write_coverage.rs` and `reads_git_midx_bitmap` in `pack_bitmap_read_git_compat.rs`.
## Fallback semantics
When bitmaps are missing, truncated, or unsupported for the requested walk:
- [`BitmapIndex::open`](https://docs.rs/grit-lib/latest/grit_lib/pack_bitmap/struct.BitmapIndex.html) returns `Ok(None)`; callers fall back to graph walks.
- Corrupt sidecars may emit diagnostics (for example EWAH or index corruption) while still completing the operation via fallback where Git would.
- [`rev_list`](https://docs.rs/grit-lib/latest/grit_lib/rev_list/fn.rev_list.html) uses bitmap fast paths when [`RevListOptions`](https://docs.rs/grit-lib/latest/grit_lib/rev_list/struct.RevListOptions.html) allow it (`--use-bitmap-index` semantics); incompatible options or shallow repos fall back transparently (see `grit-lib/tests/rev_list_bitmaps.rs`).
- [`build_pack`](https://docs.rs/grit-lib/latest/grit_lib/pack_objects/fn.build_pack.html) and upload-pack use [`enumerate_pack_objects`](https://docs.rs/grit-lib/latest/grit_lib/pack_object_select/fn.enumerate_pack_objects.html) when [`PackBuildOptions::use_bitmaps`](https://docs.rs/grit-lib/latest/grit_lib/pack_objects/struct.PackBuildOptions.html) is true and a [`BitmapIndex`](https://docs.rs/grit-lib/latest/grit_lib/pack_bitmap/struct.BitmapIndex.html) is available; otherwise the object walk runs with the same resulting set.
## Not supported yet
- **Pseudo-merge** and other experimental bitmap encodings Git may gate behind feature flags.
- **Incremental MIDX** bitmap chains (Git rejects `repack -d` with bitmaps unless `--no-write-bitmap-index`; grit does not write bitmaps for incremental repacks).
- UX-only upstream cases (`--progress`, JGit interop, `pack.preferBitmapTips` misconfiguration messages) are not CLI goals; library APIs accept explicit tip lists via `PackBitmapWriteOptions`.
## Example
```rust
//! Count objects reachable from a commit using pack/MIDX bitmaps when available.
//!
//! Usage: `cargo run --example count_reachable -- <repo> <commit>`
use std::env;
use std::process::ExitCode;
use std::sync::Arc;
use grit_lib::bitmap_walk::{BitmapWalkError, ReachabilityQuery};
use grit_lib::objects::ObjectId;
use grit_lib::pack_bitmap::BitmapIndex;
use grit_lib::repo::Repository;
use grit_lib::rev_list::MissingAction;
use grit_lib::rev_parse::resolve_revision_for_range_end;
fn main() -> ExitCode {
let mut args = env::args().skip(1);
let Some(repo_path) = args.next() else {
eprintln!("usage: count_reachable <repo> <commit>");
return ExitCode::from(2);
};
let Some(rev) = args.next() else {
eprintln!("usage: count_reachable <repo> <commit>");
return ExitCode::from(2);
};
let repo = match Repository::discover(Some(repo_path.as_ref())) {
Ok(r) => r,
Err(err) => {
eprintln!("open repository: {err}");
return ExitCode::from(1);
}
};
let commit: ObjectId = match resolve_revision_for_range_end(&repo, &rev) {
Ok(oid) => oid,
Err(err) => {
eprintln!("resolve {rev}: {err}");
return ExitCode::from(1);
}
};
let index: Arc<BitmapIndex> = match BitmapIndex::open(&repo) {
Ok(Some(idx)) => idx,
Ok(None) => {
eprintln!("no reachability bitmap in this repository");
return ExitCode::from(1);
}
Err(err) => {
eprintln!("open bitmap: {err}");
return ExitCode::from(1);
}
};
let query = ReachabilityQuery {
wants: &[commit],
haves: &[],
filter: None,
};
match index.reachability(&repo, query, MissingAction::Error) {
Ok(set) => {
println!("reachable objects: {}", set.count());
println!(
" commits: {}",
set.count_by_kind(grit_lib::objects::ObjectKind::Commit)
.unwrap_or(0)
);
println!(
" trees: {}",
set.count_by_kind(grit_lib::objects::ObjectKind::Tree)
.unwrap_or(0)
);
println!(
" blobs: {}",
set.count_by_kind(grit_lib::objects::ObjectKind::Blob)
.unwrap_or(0)
);
println!(
" tags: {}",
set.count_by_kind(grit_lib::objects::ObjectKind::Tag)
.unwrap_or(0)
);
ExitCode::SUCCESS
}
Err(BitmapWalkError::Unsupported(_)) => {
eprintln!("bitmap walk unsupported for this query (use rev-list without bitmaps)");
ExitCode::from(1)
}
Err(err) => {
eprintln!("bitmap walk failed: {err}");
ExitCode::from(1)
}
}
}
```
Run against a repository with a pack bitmap (`git repack -adb` or grit’s writer):
```bash
cargo run --example count_reachable -- /path/to/repo HEAD
```
# https://grit-scm.com/docs/library/diff/index.md
# Diff
> Tree-to-tree and index-to-worktree diffs, blob patches, and the DiffEntry model the grit CLI renders.
Diffing in grit-lib centers on [`diff`](https://docs.rs/grit-lib/latest/grit_lib/diff/index.html) and the [`diffing`](https://docs.rs/grit-lib/latest/grit_lib/diffing/index.html) module view. Results are [`DiffEntry`](https://docs.rs/grit-lib/latest/grit_lib/diff/struct.DiffEntry.html) rows with a [`DiffStatus`](https://docs.rs/grit-lib/latest/grit_lib/diff/enum.DiffStatus.html) letter (`M`, `A`, `D`, …), paths, modes, and object ids — the same shape [`grit diff`](https://grit-scm.com/docs/diff/index.md) and [`porcelain::status`](https://docs.rs/grit-lib/latest/grit_lib/porcelain/status/index.html) use before formatting output.
## Tree-to-tree
[`diff_trees`](https://docs.rs/grit-lib/latest/grit_lib/diff/fn.diff_trees.html) compares two tree objects recursively and returns changed paths. Pass `None` for either side to diff against an empty tree. [`diff_trees_show_tree_entries`](https://docs.rs/grit-lib/latest/grit_lib/diff/fn.diff_trees_show_tree_entries.html) can emit tree objects themselves (Git’s `diff-tree -t` behavior).
Commit-to-commit diffs resolve each commit’s tree with [`parse_commit`](https://docs.rs/grit-lib/latest/grit_lib/objects/fn.parse_commit.html), then call `diff_trees` on the parent and child trees.
## Index-to-worktree
[`diff_index_to_worktree`](https://docs.rs/grit-lib/latest/grit_lib/diff/fn.diff_index_to_worktree.html) compares the index to files on disk. [`diff_index_to_worktree_with_options`](https://docs.rs/grit-lib/latest/grit_lib/diff/fn.diff_index_to_worktree_with_options.html) adds index mtime, submodule/gitlink handling, broken-gitlink detection, and an optional repository git-dir override. [`porcelain::add::stage`](https://docs.rs/grit-lib/latest/grit_lib/porcelain/add/fn.stage.html) uses [`diff_index_to_worktree_for_staging`](https://docs.rs/grit-lib/latest/grit_lib/diff/fn.diff_index_to_worktree_for_staging.html) internally so staging sees the same dirty paths as status.
## Blob diffs
For a single modified file, read old and new bytes from [`Odb`](https://docs.rs/grit-lib/latest/grit_lib/odb/struct.Odb.html) and pass them to [`unified_diff`](https://docs.rs/grit-lib/latest/grit_lib/diff/fn.unified_diff.html) (histogram algorithm, Git-compatible hunks). The CLI builds human, `--json`, and `--markdown` views from `DiffEntry` lists plus optional unified bodies.
## Porcelain models
- **Status** — combines index vs HEAD and index vs worktree scans into structured sections (the CLI maps them to default / `--json` / `--markdown` output).
- **Add** — uses diff results to decide which paths to hash and stage.
- **Diff command** — tree-to-tree for commit ranges, index-to-worktree for uncommitted changes, then blob-level rendering for text files.
## Example
The program below diffs the latest commit against its parent (tree-to-tree), checks whether the work tree is dirty, and counts unified-diff lines for one modified blob:
```rust
//! Tree-to-tree, index-to-worktree, and blob diffs used by porcelain and the CLI.
//!
//! Source for the library guide "Diff" page (included in the docs site).
use grit_lib::diff::{diff_index_to_worktree, diff_trees, unified_diff, DiffEntry, DiffStatus};
use grit_lib::objects::{parse_commit, ObjectId};
use grit_lib::repo::Repository;
use grit_lib::state::resolve_head;
use std::path::{Path, PathBuf};
fn open_repo(root: &Path) -> Result<Repository, grit_lib::error::Error> {
let git_dir = if root.join(".git").is_dir() {
root.join(".git")
} else {
root.to_path_buf()
};
let work_tree = if root.join(".git").is_dir() {
Some(root)
} else {
None
};
Repository::open(&git_dir, work_tree)
}
fn tree_oid(repo: &Repository, commit: &ObjectId) -> Result<ObjectId, grit_lib::error::Error> {
let obj = repo.odb.read(commit)?;
Ok(parse_commit(&obj.data)?.tree)
}
fn print_name_status(entries: &[DiffEntry]) {
for entry in entries {
let letter = entry.status.letter();
let path = entry.path();
if entry.status == DiffStatus::Renamed {
if let (Some(old), Some(new)) = (&entry.old_path, &entry.new_path) {
println!("{letter}\t{old}\t{new}");
continue;
}
}
println!("{letter}\t{path}");
}
}
fn main() -> Result<(), grit_lib::error::Error> {
let root = std::env::args()
.nth(1)
.map(PathBuf::from)
.or_else(|| std::env::current_dir().ok())
.ok_or_else(|| grit_lib::error::Error::Message("missing repository path".into()))?;
let repo = open_repo(&root)?;
let head = resolve_head(&repo.git_dir)?;
let new_commit = head
.oid()
.cloned()
.ok_or_else(|| grit_lib::error::Error::Message("HEAD has no commit".into()))?;
let new_obj = repo.odb.read(&new_commit)?;
let new_commit_data = parse_commit(&new_obj.data)?;
let parent = new_commit_data
.parents
.first()
.copied()
.ok_or_else(|| grit_lib::error::Error::Message("need a commit with a parent".into()))?;
let old_tree = tree_oid(&repo, &parent)?;
let new_tree = new_commit_data.tree;
let tree_changes = diff_trees(&repo.odb, Some(&old_tree), Some(&new_tree), "")?;
println!("tree_diff_begin");
print_name_status(&tree_changes);
println!("tree_diff_end");
if let Some(wt) = repo.work_tree.as_deref() {
let mut index = repo.load_index()?;
let wt_changes = diff_index_to_worktree(&repo.odb, &mut index, wt, false, false)?;
println!("index_worktree_dirty={}", !wt_changes.is_empty());
}
if let (Some(entry),) = (tree_changes.first(),) {
if entry.status == DiffStatus::Modified {
let old_blob = repo.odb.read(&entry.old_oid)?.data;
let new_blob = repo.odb.read(&entry.new_oid)?.data;
let old_text = String::from_utf8_lossy(&old_blob);
let new_text = String::from_utf8_lossy(&new_blob);
let old_path = entry.old_path.as_deref().unwrap_or(entry.path());
let new_path = entry.new_path.as_deref().unwrap_or(entry.path());
let patch = unified_diff(&old_text, &new_text, old_path, new_path, 3, false, false);
let hunk_lines = patch
.lines()
.filter(|l| l.starts_with('-') || l.starts_with('+'))
.count();
println!("blob_unified_hunk_lines={hunk_lines}");
}
}
Ok(())
}
```
Requires a repository whose `HEAD` has a parent (at least two commits):
```bash
cargo run --bin guide_diff /path/to/repo
git -C /path/to/repo diff --name-status HEAD~1 HEAD
```
# https://grit-scm.com/docs/library/embedding/index.md
# Embedding grit-lib
> Run multiple repositories in one process with explicit Environment, sinks, subprocess injection, and typed errors.
Grit is designed to be **linked into other Rust programs**, not only invoked as the `grit` CLI. The library avoids hidden process globals: discovery variables, config identity, subprocesses, warnings, and wall-clock references are supplied through explicit types at the boundary.
## Environment
[`Environment`](https://docs.rs/grit-lib/latest/grit_lib/environment/struct.Environment.html) holds Git discovery and configuration variables (`GIT_DIR`, `GIT_WORK_TREE`, `GIT_CONFIG_*`, home paths, author/committer overrides, transport trace flags, and related fields). Construct it with:
- `Environment::empty()` — defaults only (`cwd = "."`).
- [`Environment::from_vars`](https://docs.rs/grit-lib/latest/grit_lib/environment/struct.Environment.html) — parse an iterator of `(key, value)` pairs plus an explicit working directory (no reads from `std::env` inside the library).
- `Environment::capture_process()` — **CLI boundary only**: snapshot the current process into an [`Environment`](https://docs.rs/grit-lib/latest/grit_lib/environment/struct.Environment.html).
Pass the same `Environment` into [`Repository`](https://docs.rs/grit-lib/latest/grit_lib/repo/struct.Repository.html) (`discover_with` / `open_with`) and into [`ConfigSet`](https://docs.rs/grit-lib/latest/grit_lib/config/struct.ConfigSet.html) loading.
## RepositoryOptions
[`RepositoryOptions`](https://docs.rs/grit-lib/latest/grit_lib/environment/struct.RepositoryOptions.html) bundles everything needed to open a repository besides paths:
| Field | Role |
| --- | --- |
| `environment` | Discovery/config/identity snapshot |
| `command_runner` | Injectable subprocess execution (hooks, filters, signing helpers) |
| `diagnostics` | [`DiagnosticSink`](https://docs.rs/grit-lib/latest/grit_lib/diagnostics/trait.DiagnosticSink.html) for warnings and trace events |
| `network_trace` | When true, emit network trace events via the diagnostics sink |
| `reference_unix_time` | Wall clock for rev-parse date selectors (`@{yesterday}`, etc.) |
| Test knobs | `test_assume_different_owner`, `force_split_index`, … |
Use `RepositoryOptions::with_environment` and `with_command_runner` on [`RepositoryOptions`](https://docs.rs/grit-lib/latest/grit_lib/environment/struct.RepositoryOptions.html); assign `diagnostics` when you need a custom sink.
## DiagnosticSink and ProgressSink
Non-fatal conditions are [`Warning`](https://docs.rs/grit-lib/latest/grit_lib/diagnostics/enum.Warning.html) values delivered to a [`DiagnosticSink`](https://docs.rs/grit-lib/latest/grit_lib/diagnostics/trait.DiagnosticSink.html). The default is [`NullDiagnostics`](https://docs.rs/grit-lib/latest/grit_lib/diagnostics/struct.NullDiagnostics.html). Tests and embedders often use [`CollectingDiagnostics`](https://docs.rs/grit-lib/latest/grit_lib/diagnostics/struct.CollectingDiagnostics.html) to assert warnings without parsing stderr.
Long-running work (status, fetch, pack indexing) takes a [`ProgressSink`](https://docs.rs/grit-lib/latest/grit_lib/progress/trait.ProgressSink.html) (for example [`NullProgress`](https://docs.rs/grit-lib/latest/grit_lib/progress/struct.NullProgress.html)). Progress is separate from diagnostics: progress reports throughput; diagnostics report Git-style warnings.
## CommandRunner
[`CommandRunner`](https://docs.rs/grit-lib/latest/grit_lib/command_runner/trait.CommandRunner.html) is the only production path that spawns OS processes from the library ([`SystemCommandRunner`](https://docs.rs/grit-lib/latest/grit_lib/command_runner/struct.SystemCommandRunner.html)). Hooks, smudge/clean filters, credential helpers, and signing helpers build a [`CommandSpec`](https://docs.rs/grit-lib/latest/grit_lib/command_runner/struct.CommandSpec.html) and call `spawn`.
For tests, [`RecordingRunner`](https://docs.rs/grit-lib/latest/grit_lib/command_runner/struct.RecordingRunner.html) records specs and returns scripted exit codes. Install it on `RepositoryOptions` before `Repository::open_with`.
## Typed errors
Library APIs return [`grit_lib::error::Result`](https://docs.rs/grit-lib/latest/grit_lib/error/type.Result.html). Match on [`Error`](https://docs.rs/grit-lib/latest/grit_lib/error/enum.Error.html) variants (`RevParse`, `RevList`, `HookError`, `FilterError`, …) instead of parsing `"fatal:"` strings. The CLI maps variants to exit codes and human messages in its own words.
## Concurrency
Two or more [`Repository`](https://docs.rs/grit-lib/latest/grit_lib/repo/struct.Repository.html) handles may be used from different threads in one process when each handle is opened with its **own** `Environment`, `RepositoryOptions`, diagnostics sink, and command runner. Repository-scoped caches (config, attributes, pack read caches) do not leak between handles.
Integration coverage: `grit-lib/tests/concurrent_repos.rs` runs parallel commit loops and a fetch/merge/notes scenario with isolated config and sinks.
## Example
```rust
//! Open two repositories in one process with isolated environments and sinks.
//!
//! Source for the library guide "Embedding" page (included in the docs site).
use std::sync::Arc;
use grit_lib::command_runner::RecordingRunner;
use grit_lib::diagnostics::{CollectingDiagnostics, DiagnosticSink};
use grit_lib::environment::{Environment, RepositoryOptions};
use grit_lib::error::Error;
use grit_lib::repo::{init_repository, Repository};
fn main() -> Result<(), Error> {
let base = tempfile::tempdir().map_err(Error::Io)?;
let open_named =
|name: &str, email: &str| -> Result<(Repository, Arc<CollectingDiagnostics>), Error> {
let root = base.path().join(name);
init_repository(
&root,
false,
"main",
None,
grit_lib::RefStorageFormat::Files,
)?;
let home = base.path().join(format!("home-{name}"));
std::fs::create_dir_all(&home).map_err(Error::Io)?;
let global = home.join(".gitconfig");
std::fs::write(
&global,
format!("[user]\n\tname = {name}\n\temail = {email}\n"),
)
.map_err(Error::Io)?;
let mut env = Environment::empty();
env.cwd = root.clone();
env.home = Some(home.into());
env.git_config_global = Some(global.to_string_lossy().into_owned());
env.git_config_nosystem = Some("true".into());
env.git_config_system = Some("/dev/null".into());
let diagnostics = Arc::new(CollectingDiagnostics::new());
let sink: Arc<dyn DiagnosticSink + Send + Sync> = diagnostics.clone();
let runner = RecordingRunner::always_success();
let mut options = RepositoryOptions::with_environment(env).with_command_runner(runner);
options.diagnostics = sink;
let git_dir = root.join(".git");
let repo = Repository::open_with(&options, &git_dir, Some(&root))?;
Ok((repo, diagnostics))
};
let (repo_a, sink_a) = open_named("alpha", "a@example.com")?;
let (repo_b, sink_b) = open_named("beta", "b@example.com")?;
let name_a = repo_a.config()?.get("user.name").unwrap_or_default();
let name_b = repo_b.config()?.get("user.name").unwrap_or_default();
println!("alpha user.name={name_a}");
println!("beta user.name={name_b}");
println!("alpha warnings={}", sink_a.warnings().len());
println!("beta warnings={}", sink_b.warnings().len());
Ok(())
}
```
Build and run:
```bash
cargo run -p grit-examples --bin guide_embedding
```
# https://grit-scm.com/docs/library/network/index.md
# Network
> Remote dispatch, fetch, push, and ls-remote over every transport.
Network operations in grit-lib center on [`Remote`](https://docs.rs/grit-lib/latest/grit_lib/remote/struct.Remote.html): a typed URL ([`RemoteUrl`](https://docs.rs/grit-lib/latest/grit_lib/remote/enum.RemoteUrl.html)), configured fetch refspecs, and one dispatcher for **fetch**, **push**, and **list refs**. Wire bytes still flow through the same fetch/push engines as before; `Remote` picks the transport from the URL scheme.
## Remote URL and config
| Scheme / form | [`RemoteUrl`](https://docs.rs/grit-lib/latest/grit_lib/remote/enum.RemoteUrl.html) variant | Transport |
| --- | --- | --- |
| Path or `file://` | `Local` / `File` | [`fetch_local`](https://docs.rs/grit-lib/latest/grit_lib/transfer/fn.fetch_local.html) / [`push_local`](https://docs.rs/grit-lib/latest/grit_lib/transfer/fn.push_local.html) |
| `git://` | `Git` | [`GitDaemonTransport`](https://docs.rs/grit-lib/latest/grit_lib/transport/struct.GitDaemonTransport.html) |
| `ssh://`, scp-style | `Ssh` | [`SshTransport`](https://docs.rs/grit-lib/latest/grit_lib/transport/struct.SshTransport.html) (repo [`CommandRunner`](https://docs.rs/grit-lib/latest/grit_lib/command_runner/trait.CommandRunner.html)) |
| `http(s)://` | `Http` / `Https` | [`http_fetch`](https://docs.rs/grit-lib/latest/grit_lib/transport/http/fn.http_fetch.html) / [`push_http`](https://docs.rs/grit-lib/latest/grit_lib/push/fn.push_http.html) |
Parse a literal URL with [`RemoteUrl::try_from`](https://docs.rs/grit-lib/latest/grit_lib/remote/enum.RemoteUrl.html). Load `remote.<name>.url`, optional `pushurl`, and `fetch` refspecs (default `+refs/heads/*:refs/remotes/<name>/*`) via [`Remote::from_config`](https://docs.rs/grit-lib/latest/grit_lib/remote/struct.Remote.html). Config applies [`url_rewrite`](https://docs.rs/grit-lib/latest/grit_lib/url_rewrite/index.html) `insteadOf` / `pushInsteadOf` rules the same way Git does.
Local paths resolve through [`resolve_local_remote_git_dir`](https://docs.rs/grit-lib/latest/grit_lib/transport_path/fn.resolve_local_remote_git_dir.html) from the repository root, not the process cwd.
## list refs
[`Remote::list_refs`](https://docs.rs/grit-lib/latest/grit_lib/remote/struct.Remote.html) takes [`ListRefsOptions`](https://docs.rs/grit-lib/latest/grit_lib/remote/struct.ListRefsOptions.html) (prefixes, heads, tags, symrefs, peel) and returns [`RemoteRef`](https://docs.rs/grit-lib/latest/grit_lib/remote/struct.RemoteRef.html) entries in `git ls-remote` order. On disk it uses [`list_refs_from_git_dir`](https://docs.rs/grit-lib/latest/grit_lib/remote/fn.list_refs_from_git_dir.html). Over the wire it uses protocol v2 `ls-refs` when available, otherwise the v0/v1 ref advertisement.
## Fetch and push
[`Remote::fetch`](https://docs.rs/grit-lib/latest/grit_lib/remote/struct.Remote.html) accepts [`FetchOptions`](https://docs.rs/grit-lib/latest/grit_lib/transfer/struct.FetchOptions.html) and a [`Progress`](https://docs.rs/grit-lib/latest/grit_lib/fetch/trait.Progress.html) sink; fetch negotiates protocol v2 when the server supports it. [`Remote::push`](https://docs.rs/grit-lib/latest/grit_lib/remote/struct.Remote.html) uses [`PushRefSpec`](https://docs.rs/grit-lib/latest/grit_lib/transfer/struct.PushRefSpec.html) and returns [`PushOutcome`](https://docs.rs/grit-lib/latest/grit_lib/transfer/struct.PushOutcome.html).
HTTP remotes need an [`HttpClient`](https://docs.rs/grit-lib/latest/grit_lib/transport/http/trait.HttpClient.html). Implement [`HttpClientFactory`](https://docs.rs/grit-lib/latest/grit_lib/remote/trait.HttpClientFactory.html) or, with the `http-ureq` feature, pass `None` to use the default ureq-backed factory (`UreqHttpClient` + [`HelperCredentialProvider`](https://docs.rs/grit-lib/latest/grit_lib/credentials/struct.HelperCredentialProvider.html)).
## Credentials and progress
[`HelperCredentialProvider`](https://docs.rs/grit-lib/latest/grit_lib/credentials/struct.HelperCredentialProvider.html) satisfies HTTP `401` responses from configured `credential.helper` programs and never opens a TTY. Pass [`NoProgress`](https://docs.rs/grit-lib/latest/grit_lib/fetch/struct.NoProgress.html) to ignore sideband progress, or implement [`Progress::message`](https://docs.rs/grit-lib/latest/grit_lib/fetch/trait.Progress.html) for side-band channel 2.
## Example
This example resolves `origin`, lists refs on a **local** bare remote, fetches, creates a commit reusing the fetched tip’s tree, and pushes — all over `file://`:
```rust
//! List refs on a local remote, fetch, create a commit, and push over `file://`.
//!
//! Source for the library guide "Network" page (included in the docs site).
use grit_examples::remote;
use grit_lib::config::ConfigSet;
use grit_lib::objects::{parse_commit, serialize_commit, CommitData, ObjectKind};
use grit_lib::refs;
use grit_lib::remote::{list_refs_from_git_dir, ListRefsOptions};
use grit_lib::repo::Repository;
use grit_lib::transfer::{FetchOptions, PushOptions, PushRefSpec, TagMode};
use grit_lib::transport_path::resolve_local_remote_git_dir;
use std::path::Path;
fn main() -> Result<(), grit_lib::error::Error> {
let consumer = std::env::args().nth(1).ok_or_else(|| {
grit_lib::error::Error::Message("usage: guide_network <consumer-repo>".to_owned())
})?;
let consumer = Path::new(&consumer);
let repo = Repository::discover(Some(consumer))?;
let git_dir = repo.git_dir.clone();
let work_tree = repo.work_tree.clone();
let config = ConfigSet::load(
&grit_lib::environment::Environment::capture_process(),
Some(&git_dir),
true,
)?;
let remote_info = remote::resolve_remote(&config, &git_dir, Some("origin"), false)
.map_err(|e| grit_lib::error::Error::Message(e.to_string()))?;
let remote_git_dir =
resolve_local_remote_git_dir(&remote_info.url, &git_dir, work_tree.as_deref());
let remote_repo = Repository::open(&remote_git_dir, None)?;
let refs_on_remote = list_refs_from_git_dir(
&remote_git_dir,
&remote_repo.odb,
&ListRefsOptions::default(),
)
.map_err(grit_lib::error::Error::from)?;
eprintln!(
"ls-remote: {} ref(s) on {}",
refs_on_remote.len(),
remote_git_dir.display()
);
let fetch_opts = FetchOptions {
refspecs: remote_info.fetch_refspecs.clone(),
tags: TagMode::Following,
..Default::default()
};
remote::fetch(&repo, &remote_info, &fetch_opts)
.map_err(|e| grit_lib::error::Error::Message(e.to_string()))?;
let tracking = refs::resolve_ref(&git_dir, "refs/remotes/origin/main")?;
refs::write_ref(&git_dir, "refs/heads/main", &tracking)?;
let parent_obj = repo.odb.read(&tracking)?;
let parent = parse_commit(&parent_obj.data)?;
let commit = CommitData {
tree: parent.tree,
parents: vec![tracking],
author: parent.author.clone(),
committer: parent.committer.clone(),
author_raw: parent.author_raw.clone(),
committer_raw: parent.committer_raw.clone(),
encoding: parent.encoding.clone(),
message: "library guide network example\n".to_owned(),
raw_message: None,
extra_headers: Vec::new(),
};
let new_oid = repo
.odb
.write(ObjectKind::Commit, &serialize_commit(&commit))?;
refs::write_ref(&git_dir, "refs/heads/main", &new_oid)?;
let spec = PushRefSpec {
src: Some(new_oid),
dst: "refs/heads/main".to_owned(),
force: false,
delete: false,
expected_old: None,
expect_absent: false,
};
remote::push(&repo, &remote_info, &[spec], &PushOptions::default())
.map_err(|e| grit_lib::error::Error::Message(e.to_string()))?;
println!("{new_oid}");
Ok(())
}
```
The `grit-examples` crate also ships `gritx-fetch` and `gritx-push`, which dispatch on URL scheme and print transport/auth discovery lines. Shared wiring lives in `grit-examples/src/remote.rs` (slated to thin over [`Remote`](https://docs.rs/grit-lib/latest/grit_lib/remote/struct.Remote.html) in a follow-up step).
Integration test `guide_network` builds bare and consumer repos with system Git, runs the binary, then requires clean `git fsck --strict` on both sides and matching `git rev-parse` on the pushed ref.
## Bundles
Git’s [bundle format](https://git-scm.com/docs/gitformat-bundle) combines a text header (prerequisite commits, ref tips, optional v3 capabilities) with a thin packfile. [`grit_lib::bundle`](https://docs.rs/grit-lib/latest/grit_lib/bundle/index.html) reads and writes that format for offline transfer and tests:
- [`Bundle`](https://docs.rs/grit-lib/latest/grit_lib/bundle/struct.Bundle.html) (`open`, `verify`, `unbundle`) and [`read_header`](https://docs.rs/grit-lib/latest/grit_lib/bundle/fn.read_header.html) parse v2/v3 headers and leave the stream at the `PACK` magic.
- `verify` checks prerequisite OIDs against the ODB and ref connectivity (matching `git bundle verify` semantics).
- `unbundle` ingests the pack via the index-pack path (`fix-thin`) and returns ref tips without updating refs.
- [`write_bundle`](https://docs.rs/grit-lib/latest/grit_lib/bundle/fn.write_bundle.html) builds v2 (SHA-1, no filter) or v3 bundles with a thin pack stream via [`pack_objects::build_pack`](https://docs.rs/grit-lib/latest/grit_lib/pack_objects/fn.build_pack.html).
- [`bundle_remote::fetch_from_bundle`](https://docs.rs/grit-lib/latest/grit_lib/bundle_remote/fn.fetch_from_bundle.html) ingests a bundle and applies fetch refspecs (clone/fetch from a `.bundle` path).
Integration test `bundle_git_compat` round-trips bundles with system `git bundle` (verify, list-heads, clone/fetch, `fsck --strict`).
# https://grit-scm.com/docs/library/object-stores/index.md
# Object stores
> Pluggable ObjectStore backends, OdbBuilder, and the odb_conformance test suite.
By default [`Repository`](https://docs.rs/grit-lib/latest/grit_lib/repo/struct.Repository.html) opens a files-backed [`Odb`](https://docs.rs/grit-lib/latest/grit_lib/odb/struct.Odb.html) (loose objects, packs, and optional MIDX). Embedders can swap the **primary** store or add read-only layers with [`OdbBuilder`](https://docs.rs/grit-lib/latest/grit_lib/odb/struct.OdbBuilder.html) and `Repository::open_with_odb`.
## Traits
| Trait | Role |
| ----- | ---- |
| [`ObjectStore`](https://docs.rs/grit-lib/latest/grit_lib/odb/store/trait.ObjectStore.html) | Read, metadata, streaming, enumeration |
| [`WritableObjectStore`](https://docs.rs/grit-lib/latest/grit_lib/odb/store/trait.WritableObjectStore.html) | Insert objects (idempotent writes) |
Built-in backends live under [`grit_lib::odb::store`](https://docs.rs/grit-lib/latest/grit_lib/odb/store/index.html) (`LooseStore`, `FilesSource`, `MemoryStore`, `CompositeStore`, and others).
## Lookup order
For a given [`Odb`](https://docs.rs/grit-lib/latest/grit_lib/odb/struct.Odb.html) handle:
1. In-memory overlay (when enabled for merge-tree-style operations)
2. **Primary** store — files source by default, or your custom [`WritableObjectStore`](https://docs.rs/grit-lib/latest/grit_lib/odb/store/trait.WritableObjectStore.html)
3. Extra read sources from `OdbBuilder::push_read_source`
4. Alternate object directories when `OdbBuilder::alternates` is true (`info/alternates`, environment alternates, submodule object dirs)
## Building a custom repository
```rust
use std::sync::Arc;
use grit_lib::environment::RepositoryOptions;
use grit_lib::objects::{HashAlgo, ObjectKind};
use grit_lib::odb::store::MemoryStore;
use grit_lib::odb::OdbBuilder;
use grit_lib::repo::{init_repository, Repository};
let dir = tempfile::tempdir()?;
init_repository(dir.path(), false, "main", None, "files")?;
let git_dir = dir.path().join(".git");
let store = Arc::new(MemoryStore::new(HashAlgo::Sha1));
let repo = Repository::open_with_odb(
&RepositoryOptions::empty(),
&git_dir,
Some(dir.path()),
OdbBuilder::files(git_dir.join("objects"))
.primary(store)
.alternates(false),
)?;
let _blob = repo.odb.write(ObjectKind::Blob, b"hello")?;
# Ok::<(), grit_lib::error::Error>(())
```
Filesystem-only maintenance (`Odb::gc`, `Odb::write_commit_graph`, `Odb::pack_store`, pack install, MIDX write) returns [`Error::UnsupportedObjectStore`](https://docs.rs/grit-lib/latest/grit_lib/error/enum.Error.html) when the primary is not the default files backend. Use `Odb::files_objects_dir` when you need the on-disk `objects/` path only for files-backed repos.
## Conformance tests
The workspace crate `grit_test_support::odb_conformance` provides shared read/write suites. Run them from an integration test in your crate (see [`grit-lib/tests/odb_conformance_memory.rs`](https://github.com/gitbutlerapp/grit/blob/main/grit-lib/tests/odb_conformance_memory.rs)) to validate a custom backend before wiring it through [`OdbBuilder`](https://docs.rs/grit-lib/latest/grit_lib/odb/struct.OdbBuilder.html).
## Example: append-only packfile KV store
`grit-examples` ships a single-file `PackfileKvStore` in `grit_examples::packfile_kv` (zlib records plus an in-memory index rebuilt on open) and a walkthrough that commits through a custom primary, walks history, and exports loose objects for system Git:
```rust
//! Custom append-only object store wired through [`OdbBuilder::primary`].
//!
//! Writes a small commit graph in the KV store, walks history with [`rev_list`],
//! then exports objects as loose files for interoperability with system Git.
use std::env;
use std::path::PathBuf;
use grit_examples::packfile_kv;
fn main() -> grit_lib::error::Result<()> {
let (root, _tmpdir) = match env::args().nth(1) {
Some(path) => (PathBuf::from(path), None),
None => {
let dir = tempfile::tempdir().map_err(grit_lib::error::Error::Io)?;
let root = dir.path().to_path_buf();
(root, Some(dir))
}
};
let log = packfile_kv::run_custom_object_store_demo(&root)?;
for oid in log {
println!("{oid}");
}
Ok(())
}
```
## Example: SQLite object database
For embedders who want indexed lookup without maintaining a separate `objects/` shard tree, `grit_examples::sqlite_odb` provides [`SqliteOdbStore`](https://github.com/gitbutlerapp/grit/blob/main/grit-examples/src/sqlite_odb.rs): each object is a row keyed by raw object id with zlib-compressed canonical store bytes (the same on-disk payload as a loose object file). The demo commits through a SQLite primary, walks history, then exports loose objects so system `git fsck` and `git log` succeed:
```rust
//! SQLite object store wired through [`OdbBuilder::primary`].
//!
//! Writes a small commit graph in SQLite, walks history with [`rev_list`],
//! then exports objects as loose files for interoperability with system Git.
use std::env;
use std::path::PathBuf;
use grit_examples::sqlite_odb;
fn main() -> grit_lib::error::Result<()> {
let (root, _tmpdir) = match env::args().nth(1) {
Some(path) => (PathBuf::from(path), None),
None => {
let dir = tempfile::tempdir().map_err(grit_lib::error::Error::Io)?;
let root = dir.path().to_path_buf();
(root, Some(dir))
}
};
let log = sqlite_odb::run_sqlite_object_store_demo(&root)?;
for oid in log {
println!("{oid}");
}
Ok(())
}
```
# https://grit-scm.com/docs/library/objects/index.md
# Objects
> ObjectId, ObjectKind, and reading or writing blobs, trees, and commits through Odb.
Git stores four object kinds grit-lib exposes as [`ObjectKind`](https://docs.rs/grit-lib/latest/grit_lib/objects/enum.ObjectKind.html). Every object is named by an [`ObjectId`](https://docs.rs/grit-lib/latest/grit_lib/objects/struct.ObjectId.html) (SHA-1 by default). The [`Odb`](https://docs.rs/grit-lib/latest/grit_lib/odb/struct.Odb.html) on [`Repository`](https://docs.rs/grit-lib/latest/grit_lib/repo/struct.Repository.html) reads loose objects and packed storage transparently.
## Writing
[`Odb::write`](https://docs.rs/grit-lib/latest/grit_lib/odb/struct.Odb.html) takes a kind and payload bytes, stores a loose object under `objects/`, and returns the id. Tree and commit bodies must already be in Git’s text format; use [`parse_tree`](https://docs.rs/grit-lib/latest/grit_lib/objects/fn.parse_tree.html) and [`parse_commit`](https://docs.rs/grit-lib/latest/grit_lib/objects/fn.parse_commit.html) when reading them back.
[`Odb::hash`](https://docs.rs/grit-lib/latest/grit_lib/odb/struct.Odb.html) (or [`HashAlgo::hash_object`](https://docs.rs/grit-lib/latest/grit_lib/objects/enum.HashAlgo.html)) computes an id without writing—useful for dry runs and tests. The algorithm follows the repository’s configured object format (SHA-1 or SHA-256).
## Reading
[`Odb::read`](https://docs.rs/grit-lib/latest/grit_lib/odb/struct.Odb.html) returns an [`Object`](https://docs.rs/grit-lib/latest/grit_lib/objects/struct.Object.html) with `kind` and uncompressed `data`. Packed and loose objects share the same API.
When you only need type and size (for example listing objects without loading blob bodies), use [`Odb::read_info`](https://docs.rs/grit-lib/latest/grit_lib/odb/struct.Odb.html) (see `read_info` on [`Odb`](https://docs.rs/grit-lib/latest/grit_lib/odb/struct.Odb.html)). It returns [`ObjectInfo`](https://docs.rs/grit-lib/latest/grit_lib/objects/struct.ObjectInfo.html) and avoids inflating full payloads for loose objects and non-delta pack entries; delta chains are resolved from headers and delta size varints only.
## Pack read caching
[`Odb`](https://docs.rs/grit-lib/latest/grit_lib/odb/struct.Odb.html) owns a repository-scoped [`PackStore`](https://docs.rs/grit-lib/latest/grit_lib/pack_store/struct.PackStore.html): pack directory listings, parsed `.idx` files, pack bytes, MIDX layers, and the delta-base LRU. Cloned [`Odb`](https://docs.rs/grit-lib/latest/grit_lib/odb/struct.Odb.html) handles share the same store; alternate object directories get separate stores on the parent [`Odb`](https://docs.rs/grit-lib/latest/grit_lib/odb/struct.Odb.html).
After repack, garbage collection, or installing a pack with [`install_pack_bytes`](https://docs.rs/grit-lib/latest/grit_lib/index_pack/fn.install_pack_bytes.html), call [`Odb::invalidate_packs`](https://docs.rs/grit-lib/latest/grit_lib/odb/struct.Odb.html) so the next read rescans `objects/pack/`. If another [`Odb`](https://docs.rs/grit-lib/latest/grit_lib/odb/struct.Odb.html) in the same process still holds a stale listing, a lookup miss retriggers directory reprepare when the pack folder’s mtime changes.
For batch reads (`cat-file --batch`, `--batch-all-objects`), wrap the loop in [`Odb::with_pack_read_context`](https://docs.rs/grit-lib/latest/grit_lib/odb/struct.Odb.html) so pack indexes, mmap-backed pack bytes, and the delta-base LRU stay on one thread-local context instead of reinstalling it per object. [`Odb::read`](https://docs.rs/grit-lib/latest/grit_lib/odb/struct.Odb.html) detects an active matching context and skips nested setup.
When iterating a pack in offset order (unordered `--batch-all-objects`), prefer [`read_object_from_pack_at_offset`](https://docs.rs/grit-lib/latest/grit_lib/pack/index.html) with the entry offset from [`PackIndex`](https://docs.rs/grit-lib/latest/grit_lib/pack/struct.PackIndex.html) so the read path does not repeat index lookup by OID.
## Pack deltas (encoding)
When building new pack deltas (as opposed to reusing on-disk zlib), grit-lib indexes the base blob with [`DeltaIndex`](https://docs.rs/grit-lib/latest/grit_lib/delta_encode/struct.DeltaIndex.html) and encodes targets with a rolling fingerprint matcher. Reuse one index across many targets in a pack-objects window; `encode` on that index accepts an optional `max_size` cap (zero means no limit). An empty target yields a valid delta (header varints only). [`encode_delta`](https://docs.rs/grit-lib/latest/grit_lib/delta_encode/fn.encode_delta.html) is a convenience wrapper for one-off base/target pairs.
## Example
This example initializes a repository, writes a blob, tree, and commit, verifies structure in memory, and prints the commit id:
```rust
//! Write a blob, tree, and commit through [`grit_lib::odb::Odb`], then read them back.
//!
//! Source for the library guide "Objects" page (included in the docs site).
use grit_lib::objects::{
parse_commit, parse_tree, serialize_commit, serialize_tree, CommitData, ObjectKind, TreeEntry,
};
use grit_lib::repo::{init_repository, Repository};
use std::path::{Path, PathBuf};
fn write_demo_objects(
repo: &Repository,
) -> Result<
(
grit_lib::objects::ObjectId,
grit_lib::objects::ObjectId,
grit_lib::objects::ObjectId,
),
grit_lib::error::Error,
> {
let blob_data = b"hello from the library guide\n";
let blob_oid = repo.odb.write(ObjectKind::Blob, blob_data)?;
let tree_entries = vec![TreeEntry {
mode: 0o100644,
name: b"README".to_vec(),
oid: blob_oid,
}];
let tree_oid = repo
.odb
.write(ObjectKind::Tree, &serialize_tree(&tree_entries))?;
let commit = CommitData {
tree: tree_oid,
parents: Vec::new(),
author: "Ada Lovelace <ada@example.com> 0 +0000".to_owned(),
committer: "Ada Lovelace <ada@example.com> 0 +0000".to_owned(),
author_raw: Vec::new(),
committer_raw: Vec::new(),
encoding: None,
message: "Library guide objects example\n".to_owned(),
raw_message: None,
extra_headers: Vec::new(),
};
let commit_oid = repo
.odb
.write(ObjectKind::Commit, &serialize_commit(&commit))?;
let tree_obj = repo.odb.read(&tree_oid)?;
let entries = parse_tree(&tree_obj.data)?;
assert_eq!(entries[0].oid, blob_oid);
let commit_obj = repo.odb.read(&commit_oid)?;
let parsed = parse_commit(&commit_obj.data)?;
assert_eq!(parsed.tree, tree_oid);
Ok((blob_oid, tree_oid, commit_oid))
}
fn open_repo(root: &Path) -> Result<Repository, grit_lib::error::Error> {
let git_dir = if root.join(".git").is_dir() {
root.join(".git")
} else {
root.to_path_buf()
};
let work_tree = if root.join(".git").is_dir() {
Some(root)
} else {
None
};
Repository::open(&git_dir, work_tree)
}
fn main() -> Result<(), grit_lib::error::Error> {
let repo = if let Some(root) = std::env::args().nth(1).map(PathBuf::from) {
open_repo(&root)?
} else {
let temp = tempfile::tempdir().map_err(grit_lib::error::Error::Io)?;
init_repository(
temp.path(),
false,
"main",
None,
grit_lib::RefStorageFormat::Files,
)?;
open_repo(temp.path())?
};
let (blob_oid, tree_oid, commit_oid) = write_demo_objects(&repo)?;
println!("{commit_oid}");
println!("blob={blob_oid} tree={tree_oid}");
Ok(())
}
```
Objects land on disk in standard loose format. System Git can read them:
```bash
cargo run --bin guide_objects /path/to/repo
git -C /path/to/repo fsck --strict
```
When run without arguments the binary uses a temporary repository (fine for `cargo run`, not for fsck demos).
# https://grit-scm.com/docs/library/pack-bitmaps/index.md
# Pack reachability bitmaps
> Read and write Git pack `.bitmap` sidecars (EWAH reachability sets, name-hash cache, lookup tables).
Git can attach a **reachability bitmap** to a pack (or multi-pack-index) so rev-list and fetch paths avoid walking the full object graph. grit-lib implements the on-disk **BITM v1** format: type bitmaps, XOR-compressed commit entries, optional name-hash cache, and optional lookup table.
## Reading
[`BitmapIndex`](https://docs.rs/grit-lib/latest/grit_lib/pack_bitmap/struct.BitmapIndex.html) on a [`Repository`](https://docs.rs/grit-lib/latest/grit_lib/repo/struct.Repository.html) loads the preferred bitmap (MIDX over pack when both exist). Decoded commit reachability sets, per-kind type filters, and optional name-hash cache entries are available on the opened index (see rustdoc on [`BitmapIndex`](https://docs.rs/grit-lib/latest/grit_lib/pack_bitmap/struct.BitmapIndex.html)).
## Writing
[`PackBitmapWriter`](https://docs.rs/grit-lib/latest/grit_lib/pack_bitmap/struct.PackBitmapWriter.html) and [`Repository::write_pack_bitmap`](https://docs.rs/grit-lib/latest/grit_lib/repo/struct.Repository.html) build a `.bitmap` for an **existing** pack index whose objects are closed under reachability from the repository’s refs—the shape produced by an all-into-one repack. Options are passed explicitly as [`PackBitmapWriteOptions`](https://docs.rs/grit-lib/latest/grit_lib/pack_bitmap/struct.PackBitmapWriteOptions.html); [`ConfigSet::pack_bitmap_write_options`](https://docs.rs/grit-lib/latest/grit_lib/config/struct.ConfigSet.html) maps Git’s `pack.writeBitmapHashCache`, `pack.writeBitmapLookupTable`, and `pack.preferBitmapTips` when you want config-driven defaults.
If no `.rev` sidecar exists, the writer creates one first so object order matches Git’s pack-offset order. Output is deterministic for identical inputs. A pack that is not closed under reachability returns [`PackBitmapWriteError::NotClosed`](https://docs.rs/grit-lib/latest/grit_lib/pack_bitmap/enum.PackBitmapWriteError.html).
## Compatibility
Integration tests in `grit-lib` round-trip against the system `git` binary (`rev-list --test-bitmap`, `--use-bitmap-index` counts). Name hashes use [`pack_name_hash`](https://docs.rs/grit-lib/latest/grit_lib/pack_name_hash/fn.pack_name_hash.html) (v1) recorded during tree walks.
# https://grit-scm.com/docs/library/refs/index.md
# Refs
> Resolve HEAD, list branches and tags, update refs with reflog, and how grit-lib picks loose, packed, or reftable storage.
References name commits (and other objects). grit-lib exposes them through [`refs`](https://docs.rs/grit-lib/latest/grit_lib/refs/index.html) and [`reftable`](https://docs.rs/grit-lib/latest/grit_lib/reftable/index.html), with [`reflog`](https://docs.rs/grit-lib/latest/grit_lib/reflog/index.html) for update history. The [`references`](https://docs.rs/grit-lib/latest/grit_lib/references/index.html) module groups these for navigation in rustdoc.
## Resolving HEAD and symbolic refs
[`resolve_head`](https://docs.rs/grit-lib/latest/grit_lib/state/fn.resolve_head.html) reads `HEAD` and returns a [`HeadState`](https://docs.rs/grit-lib/latest/grit_lib/state/enum.HeadState.html): on a branch (symbolic ref plus commit, if any), detached at a commit, or invalid. To resolve any ref name to an object id, use [`resolve_ref`](https://docs.rs/grit-lib/latest/grit_lib/refs/fn.resolve_ref.html), which follows symbolic refs with cycle detection.
[`read_ref_file`](https://docs.rs/grit-lib/latest/grit_lib/refs/fn.read_ref_file.html) returns a [`Ref`](https://docs.rs/grit-lib/latest/grit_lib/refs/enum.Ref.html) (`Direct` or `Symbolic`) without resolving the whole chain.
## Listing branches and tags
[`list_refs`](https://docs.rs/grit-lib/latest/grit_lib/refs/fn.list_refs.html) takes a prefix such as `refs/heads/` or `refs/tags/` and returns sorted `(name, ObjectId)` pairs. Loose refs under `refs/` override stale lines in `packed-refs`, matching Git. [`list_refs_glob`](https://docs.rs/grit-lib/latest/grit_lib/refs/fn.list_refs_glob.html) applies pattern matching when you need DWIM-style filtering.
## Creating and updating refs with reflog
[`write_ref`](https://docs.rs/grit-lib/latest/grit_lib/refs/fn.write_ref.html) points a ref at a commit (or other object). [`write_symbolic_ref`](https://docs.rs/grit-lib/latest/grit_lib/refs/fn.write_symbolic_ref.html) updates symbolic refs such as `HEAD`.
Record history with [`append_reflog`](https://docs.rs/grit-lib/latest/grit_lib/refs/fn.append_reflog.html), then read it back with [`read_reflog`](https://docs.rs/grit-lib/latest/grit_lib/reflog/fn.read_reflog.html). Each [`ReflogEntry`](https://docs.rs/grit-lib/latest/grit_lib/reflog/struct.ReflogEntry.html) carries old and new ids, identity, and message. Batch updates can use [`update_refs`](https://docs.rs/grit-lib/latest/grit_lib/gc/fn.update_refs.html) when you need compare-and-swap semantics across many refs.
## Loose, packed, and reftable backends
By default, grit uses the **files** backend: one file per ref under `refs/`, plus an optional `packed-refs` file. [`list_refs`](https://docs.rs/grit-lib/latest/grit_lib/refs/fn.list_refs.html) and [`resolve_ref`](https://docs.rs/grit-lib/latest/grit_lib/refs/fn.resolve_ref.html) merge packed and loose sources so callers see a single namespace.
When `extensions.refStorage = reftable` is set in config, the same functions use the **reftable** backend. Backend selection is centralized: [`open_ref_store`](https://docs.rs/grit-lib/latest/grit_lib/refs/store/fn.open_ref_store.html) detects the on-disk format from repository-local config and opens [`FilesRefStore`](https://docs.rs/grit-lib/latest/grit_lib/refs/store/struct.FilesRefStore.html) or [`ReftableRefStore`](https://docs.rs/grit-lib/latest/grit_lib/refs/store/struct.ReftableRefStore.html). An open [`Repository`](https://docs.rs/grit-lib/latest/grit_lib/repo/struct.Repository.html) caches that store on [`RepoCaches`](https://docs.rs/grit-lib/latest/grit_lib/repo_caches/struct.RepoCaches.html); call `refs()` on the handle to borrow the store, or `with_ref_store` to inject a custom backend (for example [`MemoryRefStore`](https://docs.rs/grit-lib/latest/grit_lib/refs/store/struct.MemoryRefStore.html)).
## Pluggable ref storage (`RefStore`)
[`refs::store`](https://docs.rs/grit-lib/latest/grit_lib/refs/store/index.html) defines [`RefStore`](https://docs.rs/grit-lib/latest/grit_lib/refs/store/trait.RefStore.html): raw reads, sorted prefix iteration, compare-and-swap transactions ([`RefTransaction`](https://docs.rs/grit-lib/latest/grit_lib/refs/store/struct.RefTransaction.html) → prepare/commit/abort), and reflog helpers. [`MemoryRefStore`](https://docs.rs/grit-lib/latest/grit_lib/refs/store/struct.MemoryRefStore.html) is for tests and embedders; [`FilesRefStore`](https://docs.rs/grit-lib/latest/grit_lib/refs/store/struct.FilesRefStore.html) and [`ReftableRefStore`](https://docs.rs/grit-lib/latest/grit_lib/refs/store/struct.ReftableRefStore.html) match on-disk layouts. Path-based helpers such as [`resolve_ref`](https://docs.rs/grit-lib/latest/grit_lib/refs/fn.resolve_ref.html) delegate to [`open_ref_store`](https://docs.rs/grit-lib/latest/grit_lib/refs/store/fn.open_ref_store.html); rev-parse on a [`Repository`](https://docs.rs/grit-lib/latest/grit_lib/repo/struct.Repository.html) resolves ref names through the handle's cached store.
## Example
The program below resolves `HEAD`, lists branches and tags, updates `refs/heads/library-guide-demo`, and appends a reflog entry:
```rust
//! Resolve HEAD, list branches and tags, update a branch ref with reflog.
//!
//! Source for the library guide "Refs" page (included in the docs site).
use grit_lib::objects::ObjectId;
use grit_lib::reflog::read_reflog;
use grit_lib::refs::{self, Ref};
use grit_lib::repo::Repository;
use grit_lib::state::resolve_head;
use std::path::{Path, PathBuf};
const DEMO_BRANCH: &str = "refs/heads/library-guide-demo";
fn open_repo(root: &Path) -> Result<Repository, grit_lib::error::Error> {
let git_dir = if root.join(".git").is_dir() {
root.join(".git")
} else {
root.to_path_buf()
};
let work_tree = if root.join(".git").is_dir() {
Some(root)
} else {
None
};
Repository::open(&git_dir, work_tree)
}
fn main() -> Result<(), grit_lib::error::Error> {
let root = std::env::args()
.nth(1)
.map(PathBuf::from)
.or_else(|| std::env::current_dir().ok())
.ok_or_else(|| grit_lib::error::Error::Message("missing repository path".into()))?;
let repo = open_repo(&root)?;
let git_dir = &repo.git_dir;
let head = resolve_head(git_dir)?;
match &head {
grit_lib::state::HeadState::Branch { refname, oid, .. } => {
println!("head_symbolic={refname}");
if let Some(oid) = oid {
println!("head_oid={}", oid.to_hex());
}
}
grit_lib::state::HeadState::Detached { oid } => {
println!("head_detached={}", oid.to_hex());
}
grit_lib::state::HeadState::Invalid => println!("head_invalid=1"),
}
let head_file = refs::read_ref_file(&git_dir.join("HEAD"))?;
if let Ref::Symbolic(target) = head_file {
println!("head_file_symbolic={target}");
}
for (name, oid) in refs::list_refs(git_dir, "refs/heads/")? {
println!("branch {name} {}", oid.to_hex());
}
for (name, oid) in refs::list_refs(git_dir, "refs/tags/")? {
println!("tag {name} {}", oid.to_hex());
}
println!("ref_storage={}", repo.refs().format());
let target = head
.oid()
.cloned()
.ok_or_else(|| grit_lib::error::Error::Message("HEAD has no commit".into()))?;
let old = refs::resolve_ref(git_dir, DEMO_BRANCH).ok();
refs::write_ref(git_dir, DEMO_BRANCH, &target)?;
let zero = ObjectId::zero();
let old_oid = old.as_ref().unwrap_or(&zero);
let identity = "Library Guide <guide@grit-scm.com> 1735689600 +0000";
refs::append_reflog(
git_dir,
DEMO_BRANCH,
old_oid,
&target,
identity,
"library guide refs example",
true,
)?;
println!("demo_ref={DEMO_BRANCH}");
println!("demo_oid={}", target.to_hex());
let entries = read_reflog(git_dir, DEMO_BRANCH)?;
if let Some(last) = entries.last() {
println!("demo_reflog_new={}", last.new_oid.to_hex());
println!("demo_reflog_message={}", last.message);
}
Ok(())
}
```
Run against any repository with at least one commit:
```bash
cargo run --bin guide_refs /path/to/repo
git -C /path/to/repo rev-parse refs/heads/library-guide-demo
git -C /path/to/repo reflog show refs/heads/library-guide-demo
```
# https://grit-scm.com/docs/library/repository/index.md
# Repository
> Open and discover Git repositories with an explicit Environment, read git-dir vs work tree, load config, and handle grit_lib::Error.
A [`Repository`](https://docs.rs/grit-lib/latest/grit_lib/repo/struct.Repository.html) is the main handle for grit-lib. It carries the absolute [`git_dir`](https://docs.rs/grit-lib/latest/grit_lib/repo/struct.Repository.html) path, an optional [`work_tree`](https://docs.rs/grit-lib/latest/grit_lib/repo/struct.Repository.html) for non-bare repos, an [`Odb`](https://docs.rs/grit-lib/latest/grit_lib/odb/struct.Odb.html) for object reads and writes, and the [`Environment`](https://docs.rs/grit-lib/latest/grit_lib/environment/struct.Environment.html) used to discover or open it.
## Environment
[`Environment`](https://docs.rs/grit-lib/latest/grit_lib/environment/struct.Environment.html) holds discovery and config variables (`GIT_DIR`, `GIT_WORK_TREE`, `GIT_CEILING_DIRECTORIES`, `GIT_CONFIG_*`, home paths, `cwd`, and related fields) without reading the process environment inside the library. Construct one with `Environment::empty()` (defaults only) or `Environment::from_vars()` (parse an iterator of `(key, value)` pairs plus an explicit working directory). See [`Environment`](https://docs.rs/grit-lib/latest/grit_lib/environment/struct.Environment.html).
The `grit` CLI builds an environment from the process in `grit-cli` and passes it into discovery. Embedders should do the same: snapshot the variables you care about once, then call `Repository::discover_with` or `Repository::open_with` with [`RepositoryOptions`](https://docs.rs/grit-lib/latest/grit_lib/environment/struct.RepositoryOptions.html).
[`Repository::discover`](https://docs.rs/grit-lib/latest/grit_lib/repo/struct.Repository.html) and [`Repository::open`](https://docs.rs/grit-lib/latest/grit_lib/repo/struct.Repository.html) remain convenience entry points that use `Environment::empty()` (no overrides beyond `cwd = "."`).
[`ConfigSet::load`](https://docs.rs/grit-lib/latest/grit_lib/config/struct.ConfigSet.html) takes `&Environment` as its first argument and always parses the cascade from disk (no process-global cache). Repository-scoped memoization lives on each open handle: [`Repository::config`](https://docs.rs/grit-lib/latest/grit_lib/repo/struct.Repository.html) returns `Arc<ConfigSet>` backed by [`RepoCaches`](https://docs.rs/grit-lib/latest/grit_lib/repo_caches/struct.RepoCaches.html) (config cascade, gitattributes stacks, filter-process drivers, precompose flags, and related state).
## Command runner
Hooks, clean/smudge filters, credential helpers, signing, SSH transport, and similar features spawn subprocesses through a [`CommandRunner`](https://docs.rs/grit-lib/latest/grit_lib/command_runner/trait.CommandRunner.html) stored on the repository (via [`RepositoryOptions::command_runner`](https://docs.rs/grit-lib/latest/grit_lib/environment/struct.RepositoryOptions.html)). The default is [`SystemCommandRunner`](https://docs.rs/grit-lib/latest/grit_lib/command_runner/struct.SystemCommandRunner.html), which is the only non-test code path that calls `std::process::Command`. Tests and embedders can install [`RecordingRunner`](https://docs.rs/grit-lib/latest/grit_lib/command_runner/struct.RecordingRunner.html) or a custom runner to assert argv, environment, and stdin without executing real programs. Hook failures surface as [`HookError`](https://docs.rs/grit-lib/latest/grit_lib/hooks/enum.HookError.html); shell filter subprocess failures use [`FilterError`](https://docs.rs/grit-lib/latest/grit_lib/error/enum.FilterError.html).
## Discover vs open
Call `Repository::discover_with` when you have a working directory and want Git-style upward search. Call `Repository::open_with` when you already know the git directory and optionally the work tree path. See [`Repository`](https://docs.rs/grit-lib/latest/grit_lib/repo/struct.Repository.html).
Bare repositories have `work_tree: None`. Linked worktrees and gitfile indirection are handled during discovery so `git_dir` always points at the directory that contains `objects/`.
## Config
[`Repository::config`](https://docs.rs/grit-lib/latest/grit_lib/repo/struct.Repository.html) returns a lazily loaded snapshot of the merged cascade (system / global / local / worktree / environment overrides). Prefer it on hot paths instead of calling `ConfigSet::load` repeatedly. Keys use Git’s dotted names (`user.name`, `core.bare`, …).
## Errors
Library operations return [`grit_lib::error::Result`](https://docs.rs/grit-lib/latest/grit_lib/error/type.Result.html). The [`Error`](https://docs.rs/grit-lib/latest/grit_lib/error/enum.Error.html) enum covers I/O, missing objects, bad repository layout, and invalid user input. Match on variants in application code; the `grit` CLI maps them to exit codes and messages separately.
## Example
The program below discovers a repository (or opens `.git` in the current directory), prints paths, and reads `user.name` from config:
```rust
//! Open and discover repositories; load config from the git directory.
//!
//! Source for the library guide "Repository" page (included in the docs site).
use grit_lib::config::ConfigSet;
use grit_lib::environment::{Environment, RepositoryOptions};
use grit_lib::error::Error;
use grit_lib::repo::Repository;
fn main() -> Result<(), Error> {
let cwd = std::env::current_dir().map_err(Error::Io)?;
let env = Environment::from_vars(std::env::vars_os(), cwd.clone());
let options = RepositoryOptions::with_environment(env.clone());
let repo = match Repository::discover_with(&options, None) {
Ok(r) => r,
Err(Error::NotARepository(_)) => {
let git_dir = cwd.join(".git");
Repository::open_with(&options, &git_dir, Some(&cwd))?
}
Err(err) => return Err(err),
};
println!("git_dir={}", repo.git_dir.display());
if let Some(wt) = &repo.work_tree {
println!("work_tree={}", wt.display());
} else {
println!("work_tree=<bare>");
}
let cfg = ConfigSet::load(repo.environment(), Some(&repo.git_dir), true)?;
let name = cfg.get("user.name").unwrap_or_default();
if !name.is_empty() {
println!("user.name={name}");
}
Ok(())
}
```
Run from any Git checkout:
```bash
cargo run --bin guide_repository
```
# https://grit-scm.com/docs/library/revwalk/index.md
# Revwalk
> Resolve revisions, walk history with rev-list, ranges (A..B), ordering, and merge bases.
History walks start from one or more **tips** (resolved ref names or expressions), follow parent links, optionally subtract another set of tips, then sort the result. grit-lib exposes the same machinery the CLI uses through [`rev_parse`](https://docs.rs/grit-lib/latest/grit_lib/rev_parse/index.html) and [`rev_list`](https://docs.rs/grit-lib/latest/grit_lib/rev_list/index.html).
## Rev-parse
[`resolve_revision`](https://docs.rs/grit-lib/latest/grit_lib/rev_parse/fn.resolve_revision.html) turns a single spec (`HEAD`, `main`, `v1.0`, `abc1234`, `main^`, `HEAD~3`, tag peelers, and more) into an [`ObjectId`](https://docs.rs/grit-lib/latest/grit_lib/objects/struct.ObjectId.html). For range endpoints and log-style DWIM, [`resolve_revision_for_range_end`](https://docs.rs/grit-lib/latest/grit_lib/rev_parse/fn.resolve_revision_for_range_end.html) matches Git’s `A..B` left/right rules.
Common helpers that do not need a full repository walk:
- [`split_double_dot_range`](https://docs.rs/grit-lib/latest/grit_lib/rev_parse/fn.split_double_dot_range.html) — split `main..feature` into two tokens (ignores `...` and path segments).
- [`abbreviate_ref_name`](https://docs.rs/grit-lib/latest/grit_lib/rev_parse/fn.abbreviate_ref_name.html) — shorten `refs/heads/main` to `main` for display.
## Rev-list
[`rev_list`](https://docs.rs/grit-lib/latest/grit_lib/rev_list/fn.rev_list.html) takes positive and negative revision specs plus [`RevListOptions`](https://docs.rs/grit-lib/latest/grit_lib/rev_list/struct.RevListOptions.html). It returns a [`RevListResult`](https://docs.rs/grit-lib/latest/grit_lib/rev_list/struct.RevListResult.html) whose `commits` field is the final oid list (after skip, max-count, and reverse).
| Option | Meaning |
| --- | --- |
| [`ordering`](https://docs.rs/grit-lib/latest/grit_lib/rev_list/struct.RevListOptions.html) | [`OrderingMode`](https://docs.rs/grit-lib/latest/grit_lib/rev_list/enum.OrderingMode.html) — default date order, topo, author-date variants. |
| `first_parent` | Follow only the first parent at merges. |
| `max_count` / `skip` | Limit how many commits are returned. |
| `reverse` | Reverse the selected list after sorting. |
For a range `main..feature`, pass `feature` as a positive spec and `main` as a negative spec (or split with [`split_double_dot_range`](https://docs.rs/grit-lib/latest/grit_lib/rev_parse/fn.split_double_dot_range.html) as the example does). That matches `git rev-list main..feature`.
## Merge base
[`merge_bases_first_vs_rest`](https://docs.rs/grit-lib/latest/grit_lib/merge_base/fn.merge_bases_first_vs_rest.html) finds minimal common ancestors between one commit and one or more others — the library equivalent of `git merge-base A B`. For diff-style “pick exactly one base or fail”, see [`merge_base_for_diff_two_commits`](https://docs.rs/grit-lib/latest/grit_lib/merge_base/fn.merge_base_for_diff_two_commits.html).
## Example
The program below opens a repository (created by system Git in tests), walks `main..feature`, prints each commit oid, then prints the merge base of the range tips:
```rust
//! Walk commit history with [`grit_lib::rev_list::rev_list`] and compute a merge base.
//!
//! Source for the library guide "Revwalk" page (included in the docs site).
use grit_lib::merge_base::merge_bases_first_vs_rest;
use grit_lib::repo::Repository;
use grit_lib::rev_list::{rev_list, RevListOptions};
use grit_lib::rev_parse::{resolve_revision, split_double_dot_range};
use std::path::Path;
fn main() -> Result<(), grit_lib::error::Error> {
let mut args = std::env::args().skip(1);
let repo_root = args.next().map(std::path::PathBuf::from).ok_or_else(|| {
grit_lib::error::Error::Message("usage: guide_revwalk <repo> [main..feature]".to_owned())
})?;
let range = args.next().unwrap_or_else(|| "main..feature".to_owned());
let repo = open_repo(&repo_root)?;
let options = RevListOptions::default();
let result = if let Some((left, right)) = split_double_dot_range(&range) {
let mut positive = Vec::new();
let mut negative = Vec::new();
if !right.is_empty() {
positive.push(right.to_owned());
}
if !left.is_empty() {
negative.push(left.to_owned());
}
rev_list(&repo, &positive, &negative, &options)?
} else {
rev_list(&repo, std::slice::from_ref(&range), &[], &options)?
};
for oid in &result.commits {
println!("{oid}");
}
let (left_name, right_name) = range_names(&range)?;
let left = resolve_revision(&repo, left_name)?;
let right = resolve_revision(&repo, right_name)?;
let bases = merge_bases_first_vs_rest(&repo, left, &[right])?;
let Some(base) = bases.first() else {
return Err(grit_lib::error::Error::Message(
"no merge base for range tips".to_owned(),
));
};
println!("merge_base={base}");
Ok(())
}
fn open_repo(root: &Path) -> Result<Repository, grit_lib::error::Error> {
let git_dir = if root.join(".git").is_dir() {
root.join(".git")
} else {
root.to_path_buf()
};
let work_tree = if root.join(".git").is_dir() {
Some(root)
} else {
None
};
Repository::open(&git_dir, work_tree)
}
fn range_names(range: &str) -> Result<(&str, &str), grit_lib::error::Error> {
split_double_dot_range(range).ok_or_else(|| {
grit_lib::error::Error::Message(format!("expected a double-dot range, got {range:?}"))
})
}
```
Run against a repo with diverged `main` and `feature` branches:
```bash
cargo run --bin guide_revwalk /path/to/repo main..feature
```
The integration test `guide_revwalk` checks commit order against `git rev-list` and the merge base against `git merge-base`.
# https://grit-scm.com/docs/library/staging/index.md
# Index
> Load the staging index, stage paths with porcelain add, and write a tree object from staged entries.
The Git index (staging area) lives in [`Index`](https://docs.rs/grit-lib/latest/grit_lib/index/struct.Index.html). Open a [`Repository`](https://docs.rs/grit-lib/latest/grit_lib/repo/struct.Repository.html), then call `load_index` (or `write_index` after changes). Index-related modules are grouped under [`worktree_index`](https://docs.rs/grit-lib/latest/grit_lib/worktree_index/index.html) in rustdoc.
See also the [Repository](https://grit-scm.com/docs/library/repository/index.md) and [Objects](https://grit-scm.com/docs/library/objects/index.md) pages for opening repos and writing objects. Other library topics: [Refs](https://grit-scm.com/docs/library/refs/index.md), [Diff](https://grit-scm.com/docs/library/diff/index.md).
## Reading the index
[`Index`](https://docs.rs/grit-lib/latest/grit_lib/index/struct.Index.html) `load` reads `index` from disk; [`Repository`](https://docs.rs/grit-lib/latest/grit_lib/repo/struct.Repository.html) `load_index` applies sparse-checkout and split-index rules the same way porcelain commands do. Entries are [`IndexEntry`](https://docs.rs/grit-lib/latest/grit_lib/index/struct.IndexEntry.html) values with path, mode, object id, and stage.
## Staging paths
[`porcelain::add::stage`](https://docs.rs/grit-lib/latest/grit_lib/porcelain/add/fn.stage.html) compares the index to the work tree once, hashes changed blobs, and writes the index back. Pass [`StageOptions`](https://docs.rs/grit-lib/latest/grit_lib/porcelain/add/struct.StageOptions.html) for pathspecs and [`StageMode`](https://docs.rs/grit-lib/latest/grit_lib/porcelain/add/enum.StageMode.html) (`All` vs `Update`). Long-running staging reports through a [`ProgressSink`](https://docs.rs/grit-lib/latest/grit_lib/progress/trait.ProgressSink.html); examples use [`NullProgress`](https://docs.rs/grit-lib/latest/grit_lib/progress/struct.NullProgress.html) when no UI is needed.
The `grit add` command is a thin wrapper around this API.
## Writing a tree from the index
[`write_tree_from_index`](https://docs.rs/grit-lib/latest/grit_lib/write_tree/fn.write_tree_from_index.html) builds a tree object from stage-0 entries (respecting the optional path prefix). It returns the root [`ObjectId`](https://docs.rs/grit-lib/latest/grit_lib/objects/struct.ObjectId.html). When the index cache-tree extension is valid, grit reuses cached subtree oids for speed; otherwise it walks entries and writes new tree objects through [`Odb`](https://docs.rs/grit-lib/latest/grit_lib/odb/struct.Odb.html).
## Example
This program loads the index, stages new or changed paths, and prints the tree oid grit would commit:
```rust
//! Read the index, stage paths, and write a tree from staged entries.
//!
//! Source for the library guide "Index" page (included in the docs site).
use grit_lib::porcelain::add::{stage, StageOptions};
use grit_lib::progress::NullProgress;
use grit_lib::repo::{init_repository, Repository};
use grit_lib::write_tree::write_tree_from_index;
use std::fs;
use std::path::{Path, PathBuf};
fn open_repo(root: &Path) -> Result<Repository, grit_lib::error::Error> {
let git_dir = if root.join(".git").is_dir() {
root.join(".git")
} else {
root.to_path_buf()
};
let work_tree = if root.join(".git").is_dir() {
Some(root)
} else {
None
};
Repository::open(&git_dir, work_tree)
}
fn main() -> Result<(), grit_lib::error::Error> {
let mut temp_guard = None;
let repo = if let Some(root) = std::env::args().nth(1).map(PathBuf::from) {
open_repo(&root)?
} else {
let temp = tempfile::tempdir().map_err(grit_lib::error::Error::Io)?;
init_repository(
temp.path(),
false,
"main",
None,
grit_lib::RefStorageFormat::Files,
)?;
let path = temp.path().join("hello.txt");
fs::write(&path, b"staged from the library guide\n").map_err(grit_lib::error::Error::Io)?;
let opened = open_repo(temp.path())?;
temp_guard = Some(temp);
opened
};
let _keep = temp_guard;
let index = repo.load_index()?;
println!("index_entries={}", index.entries().len());
let outcome = stage(&repo, &StageOptions::default(), &mut NullProgress)?;
println!(
"staged added={} modified={} removed={}",
outcome.added, outcome.modified, outcome.removed
);
let index = repo.load_index()?;
let tree_oid = write_tree_from_index(&repo.odb, &index, "")?;
println!("tree_oid={}", tree_oid.to_hex());
Ok(())
}
```
With a repository path, compare the printed tree to Git:
```bash
cargo run --bin guide_index /path/to/repo
git -C /path/to/repo write-tree
git -C /path/to/repo fsck --strict
```
Without arguments the binary uses a temporary repository (useful for `cargo run`, not for fsck demos).
# https://grit-scm.com/docs/benchmarks/index.md
# Benchmarks
> Grit vs Git on realistic workloads, from the committed grit-bench baseline.
Performance work is measured on the factory VM and in CI against the **system** `git` binary. Micro-benchmarks live in `grit-lib` (Criterion) and command-level scenarios in `grit-bench` (`grit-utils`).
Command-level numbers below come from the committed **grit-bench** JSON baselines listed in `content/docs/site.toml`. Each scenario runs **hyperfine** against the system **`git`** binary and a release **`grit`** build on the same machine; times are wall-clock milliseconds (mean and spread from timed runs).
## grit-lib: parallel object hashing
Criterion group `hash/batch_parallel` (`cargo bench -p grit-lib --bench objects hash/batch_parallel`) hashes **20 000** Git blob objects of **16 KiB** each using [`hash_objects_parallel`](https://docs.rs/grit-lib/latest/grit_lib/hash/fn.hash_objects_parallel.html) (SHA-1, release build).
| Threads | Time (median) | Throughput |
| ------- | ------------- | ---------- |
| 1 | 173 ms | 1.76 GiB/s |
| 8 | 44.5 ms | 6.86 GiB/s |
**Speedup (8 vs 1 thread): ~3.9×** on the factory VM (2026-10-07).
Parallel hashing falls back to a serial loop when there are fewer than [`PAR_HASH_MIN_ITEMS`](https://docs.rs/grit-lib/latest/grit_lib/hash/constant.PAR_HASH_MIN_ITEMS.html) (32) objects or less than [`PAR_HASH_MIN_TOTAL_BYTES`](https://docs.rs/grit-lib/latest/grit_lib/hash/constant.PAR_HASH_MIN_TOTAL_BYTES.html) (256 KiB) of payload, so small batches avoid thread overhead.
## grit-lib: ODB backend (pluggable object store)
Criterion group **`odb_backend`** compares post-refactor [`Odb`](https://docs.rs/grit-lib/latest/grit_lib/odb/struct.Odb.html) against the saved baseline **`odb-before`** (`cargo bench -p grit-lib --bench odb_backend -- --baseline odb-before`). Built-in layouts route hot reads through [`FilesSource`](https://docs.rs/grit-lib/latest/grit_lib/odb/store/struct.FilesSource.html) on the primary store and [`CompositeStore`](https://docs.rs/grit-lib/latest/grit_lib/odb/store/struct.CompositeStore.html) for alternates so behaviour matches the pre-refactor oracle tests while keeping a pluggable [`ObjectStore`](https://docs.rs/grit-lib/latest/grit_lib/odb/store/trait.ObjectStore.html) boundary.
**Pluggable object store overhead (factory VM, 2026-10-09):** Re-run Criterion with `--baseline odb-before` after ODB changes; command-level **`grit-bench odb-backend`** baselines are in **`odb-backend-before.json`** (pre-refactor capture, scenario ids suffixed `-pre-refactor`) and **`odb-backend-after.json`**. Post-refactor Grit medians for cat-file batch/check are much lower than the pre-refactor capture on the same fixture; rev-list wall time is similar while Grit/Git **ratios** can drift when system `git` speeds up between runs.
Criterion measures [`Odb::read`](https://docs.rs/grit-lib/latest/grit_lib/odb/struct.Odb.html), [`read_info`](https://docs.rs/grit-lib/latest/grit_lib/odb/struct.Odb.html#method.read_info), [`exists`](https://docs.rs/grit-lib/latest/grit_lib/odb/struct.Odb.html#method.exists) (hit and miss), and [`write`](https://docs.rs/grit-lib/latest/grit_lib/odb/struct.Odb.html#method.write) on four deterministic layouts built in `grit-lib/benches/fixture.rs`:
| Fixture | Shape |
| --- | --- |
| `loose_10k` | 10 000 loose blobs, no packs |
| `pack_100k` | Single repacked pack (~100 000 objects) |
| `midx_8` | Eight pack layers with multi-pack-index (`git prune-packed` so hits are pack-only, not loose) |
| `alternate_only` | Primary store empty; objects only in an alternate |
An additional benchmark, **`odb_backend/exists_miss_loop_10k`**, calls `exists` on 10 000 distinct missing OIDs against the 100k pack fixture (models add/status miss scans).
Command-level ODB scenarios on the repacked **100k-file / 1000-commit** synthetic repo live in **`grit-utils/baselines/odb-backend-before.json`** and **`grit-utils/baselines/odb-backend-after.json`** (`grit-bench odb-backend`): library drivers (`grit-bench drive …`) vs **`git cat-file --batch`**, **`git cat-file --batch-check`**, and **`git rev-list --objects --all`** on the same sorted OID stdin list where applicable.
```bash
cargo build --release -p grit-utils
./target/release/grit-bench odb-backend --format json --output grit-utils/baselines/odb-backend-after.json
cargo bench -p grit-lib --bench odb_backend -- --baseline odb-before
make docs
```
Run `grit-bench odb-backend` once before the Criterion command (or leave a populated `GRIT_BENCH_ODB_CACHE`) so the `pack_100k` fixture reuses the repacked 100k repo instead of rebuilding 100k commits inline.
**Recorded on the factory VM (2026-10-09, repacked 100k synthetic repo).** Pre-refactor numbers are in **`odb-backend-before.json`**; post-refactor in **`odb-backend-after.json`** (also drives the generated ODB rows below).
| Scenario | Git median | Grit median (before → after) | Grit / Git (before → after) |
| --- | ---: | ---: | ---: |
| `cat-file-batch-hot-path-100k` | ~144 ms | 1 117 ms → ~356 ms | **7.4× → ~2.5×** |
| `cat-file-batch-check-hot-path-100k` | ~52 ms | 1 261 ms → ~239 ms | **24.2× → ~5.2×** |
| `rev-list-objects-odb-backend-hot-path-100k` | ~65 ms | 6 916 ms → ~6 189 ms | **99.1× → ~96×** |
Rev-list **ratios** can rise when system **`git`** speeds up between captures even if Grit wall time improves; compare absolute Grit medians when judging regressions.
The rev-list gap is dominated by history/object enumeration in `grit-lib`, not bulk pack I/O; cat-file scenarios exercise ODB read and `read_info` paths directly.
## grit-bench: reachability bitmaps (`git.git`)
Scenario group **`bitmaps`** measures three acceptance metrics on upstream **`git/git`**: commit counting, object counting with bitmap index, and stateless **`upload-pack`** clone serving. The fixture is a bare **single-branch tag clone** at **`v2.47.0`** (override with **`GRIT_BENCH_GIT_GIT_TAG`**) under **`GRIT_BENCH_ODB_CACHE`**, prepared once with **Git-written** pack bitmaps (`git repack -adb`, `git commit-graph write --reachable`) and separately with **grit-written** pack bitmaps (`git repack -ad`, commit-graph, then `PackBitmapWriter` — see `ensure_bitmaps_grit_repo` in `grit-utils/src/bitmap_fixture.rs`). Library workloads use hidden **`grit-bench drive`** commands (`rev-list-count`, `rev-list-count-objects`, `serve-clone`); Git runs the equivalent **`git rev-list`** / **`git upload-pack`** invocations with the same isolated config as other grit-bench suites.
**Methodology.** Hyperfine warmups and minimum runs match other factory captures (see each JSON `machine` block). Ratios are **Grit median ÷ Git median**. **Peak RSS** is recorded per side via `grit-bench measure-rss` / hyperfine wrappers. **`serve-clone`** runs under **`GRIT_BENCH_SERVE_TIMEOUT_SECS`** (default **120**) and **`GRIT_BENCH_SERVE_MAX_RSS_GIB`** (default **12**). Reproducibility: run the suite twice back-to-back on the same fixture; medians should agree within **±10% relative** (`grit-bench compare … --tolerance 0.10` uses an absolute ratio tolerance — interpret large ratios accordingly).
```bash
cargo build --release -p grit-utils -p grit-cli
./target/release/grit-bench bitmaps --format json --output grit-utils/baselines/bitmaps-after.json
# Optional grit-written pack bitmap sidecar (separate JSON; default fixture stays Git-prepared):
GRIT_BENCH_BITMAP_FIXTURE=grit ./target/release/grit-bench bitmaps --format json --output grit-utils/baselines/bitmaps-grit-written.json
```
**Before (`bitmaps-before.json`, 2026-10-10, pre-reader/writer stack):** bitmap reader missing — object count ~**23 000×** vs Git; serve-clone hit **memory_cap**.
**After acceptance (`bitmaps-after.json`, factory VM 2026-10-16, release `grit` on the pack-reuse + bitmap stack):**
| Scenario | Git median | Grit median | Ratio | Grit peak RSS |
| --- | ---: | ---: | ---: | ---: |
| `rev-list-count-git.git` | 57.3 ms | 1033.2 ms | **18.0×** | ~285 MiB |
| `rev-list-count-objects-git.git` | 16.8 ms | 1064.6 ms | **63.2×** | ~286 MiB |
| `serve-clone-git.git` | 691.6 ms | *(120 s cap)* | — | timeout (`exit 124`) |
Two back-to-back runs on the git-prepared fixture (2026-10-16) agreed within **~6–8% relative** on Grit medians for the rev-list scenarios (`971 ms` vs `1033 ms` count; `984 ms` vs `1065 ms` object count).
**Grit-written bitmap fixture:** set **`GRIT_BENCH_BITMAP_FIXTURE=grit`** when running `grit-bench bitmaps` to prepare the same pinned **`git.git`** clone with **`git repack -ad`**, commit-graph, and a grit-lib **`PackBitmapWriter`** sidecar (`ensure_bitmaps_grit_repo`). The committed **`bitmaps-after.json`** uses the **Git-prepared** fixture (default); capture a separate JSON for grit-written bitmaps when comparing interoperability (see factory notes for the grit-fixture run ratios).
**Acceptance bar (roadmap item 14):** each ratio **≤ 1.2×** (and serve-clone within the same bar). The after run **passes compatibility** (bitmaps read/write, serve packs validate with `git index-pack --strict` after the thin-pack reuse fix) but **misses the 1.2× performance bar** on all three command-level metrics on this tag-heavy **`git.git`** fixture (~954 tag refs). Follow-ups (not retargeting the bar):
- **Multi-tip bitmap counting:** optimize `rev-list --count --all` / `--objects --use-bitmap-index` when hundreds of tag tips are present (Git ~60 ms vs grit ~1 s on the same fixture).
- **Serve-clone wall time:** upload-pack on the full closure must complete under the factory serve cap without timing out; profile pack reuse + enumeration on `git.git`.
- **Re-run `bitmaps-after.json`** after those land; keep **`bitmaps-before.json`** for regression context.
Intermediate capture on the same VM before the final writer stack (**2026-10-10**) remains in **`bitmaps-before.json`** for the generated tables (`rev-list-count` **~3.3×**, object count unusable, serve **memory_cap**).
## grit-lib: parallel index-pack (in-memory)
Hyperfine on a **~90 000-object** depth-50 pack (`git fast-import` + `git repack -adf --depth=50`, factory VM 2026-10-07). Grit uses [`pack_index_records_with_threads`](https://docs.rs/grit-lib/latest/grit_lib/unpack_objects/fn.pack_index_records_with_threads.html) via `cargo run --release -p grit-lib --example index_pack_bench` (see `GRIT_INDEX_PACK_BENCH_PACK` / `GRIT_INDEX_PACK_THREADS`).
| Command | Mean (8 runs) |
| ------- | ------------- |
| `git index-pack --threads=8` | 640 ms |
| grit index-pack, 1 thread | 1.43 s |
| grit index-pack, 8 threads | 781 ms |
**Speedup (8 vs 1 thread): ~1.83×** on this fixture. Multi-threaded builds discover object boundaries with a discard decompress pass, then parallel workers inflate and hash whole objects; delta chains inflate, apply, and hash in parallel rounds. Grit does not yet beat `git index-pack --threads=8` on this pack (Git also writes the on-disk `.idx`).
Integration coverage uses a **≥ 50 000** object fixture built with `git fast-import` and shared across tests via `OnceLock` (`grit-lib/tests/index_pack_parallel.rs`); the default release suite completes in about **41 s** on the factory VM.
## Hashing
Raw digest throughput uses [`grit_lib::hash::ObjectHasher`](https://docs.rs/grit-lib/latest/grit_lib/hash/enum.ObjectHasher.html) (release build, Criterion). OpenSSL numbers are from `openssl speed -evp sha1 -bytes 16384` and `openssl speed -evp sha256` (16 KiB blocks where shown). Git blob hashing uses `git hash-object` on a 256 MiB file vs the `gritx-hash-file` example (same canonical blob object id, no object-database write).
**Environment (2026-10-07):** Intel Xeon (SHA-NI present), Linux, `git` 2.43.0, OpenSSL 3.0.13, Rust stable. `hash-info --json` reports `{"sha1":"x86_sha_ni","sha256":"x86_sha_ni"}`.
| Workload | grit-lib | Reference | grit / reference |
| -------- | -------- | --------- | ---------------- |
| SHA-1, 1 MiB buffer | 1.98 GiB/s | OpenSSL SHA-1 @ 16 KiB: 1.98 GiB/s | **100%** |
| SHA-256, 1 MiB buffer | 1.80 GiB/s | OpenSSL SHA-256 @ 16 KiB: 1.78 GiB/s | **101%** |
| SHA-1 blob, 256 MiB file | 0.31 s | `git hash-object`: 0.48 s | **1.55× faster** |
SHA-1 at 1 MiB and above meets the project bar (≥ 95% of OpenSSL on the same CPU). SHA-256 meets ≥ 90% of OpenSSL. End-to-end blob id for a large file beats stock Git 2.43, which still uses sha1dc for object hashing.
### Commands
```bash
# Backends selected on this CPU
cargo run -p grit-examples --bin hash-info -- --json
# Criterion throughput (64 B … 64 MiB)
cargo bench -p grit-lib --bench hash
# OpenSSL + hyperfine vs git (creates a 256 MiB temp file)
./scripts/bench-hash.sh
```
## grit-bench vs Git
### Methodology
- **Fixtures** use synthetic repos at large file counts and deep history, built deterministically in a scratch directory.
- **Drivers** are CLI invocations of `grit` and `git` with equivalent semantics (not argv-for-argv compatibility).
- **Ratios** are **Grit median ÷ Git median** (stored in each scenario’s `ratio` field; hyperfine also records mean and spread). Values below `1.00×` mean Grit is faster; values above `2.00×` are highlighted as regressions worth investigating.
- **Spread** shows Grit’s standard deviation across timed runs (hyperfine `--min-runs` / warmup settings from the baseline capture).
### Reproduce locally
Build release binaries, install [hyperfine](https://github.com/sharkdp/hyperfine), then run matching grit-bench scenarios from the repo root (see `grit-utils/README.md` for the current subcommands):
```bash
cargo build --release -p grit-cli -p grit-utils
# Example: hot-path scenarios at L/H tiers (switch, pick, merge)
./target/release/grit-bench hot-paths --sizes 10000,100000 --format json --output /tmp/grit-bench-hot-paths.json
```
When roadmap item 2 adds more baseline JSON files on `main`, list their paths under `[benchmarks].baseline` in `content/docs/site.toml` and regenerate the site.
Compare a fresh run against the committed baseline (exit non-zero if any scenario ratio drifts beyond tolerance):
```bash
./target/release/grit-bench compare grit-utils/baselines/hot-paths-before.json /tmp/grit-bench-hot-paths.json --tolerance 0.10
```
### Hot-path acceptance (maintenance plan step 386)
Recorded on the factory VM after stacking pick/merge/stash perf work on `origin/main`. **Before** numbers are in `grit-utils/baselines/hot-paths-before.json` (2026-10-07); **after** in `grit-utils/baselines/hot-paths-after.json` (2026-10-08). Config isolation (`GIT_CONFIG_NOSYSTEM`, empty global config) applies to hot-path, suite `commit`, and related scenarios. FSMN variants: `grit-utils/baselines/hot-paths-after-fsmn.json`.
**Machine (2026-10-08 acceptance):** Intel Xeon (factory VM), **4** physical / **4** logical CPUs, **16 GiB** RAM, Linux **6.12.94+**, scratch filesystem **ext4**, `rustc` **1.99.0**, `git` **2.43.0**, release `grit` **0.5.1**, hyperfine **2.x** (see `machine` in each baseline JSON).
**Machine (2026-10-09 refresh):** same factory VM (Intel Xeon, **4** / **4** CPUs, **16 GiB** RAM, Linux **6.12.94+**, ext4 scratch), `rustc` **1.99.0**, `git` **2.43.0**, release `grit` **0.5.3** at **`01a254dc`**, hyperfine **2.0.0**. Committed baselines were regenerated with `./target/release/grit-bench {hot-paths,commit,all} --sizes 10000,100000` (default warmup / min-runs).
| Scenario | L before × | L 2026-10-08 × | L 2026-10-09 × | H before × | H 2026-10-08 × | H 2026-10-09 × | Notes |
| --- | ---: | ---: | ---: | ---: | ---: | ---: | --- |
| `add` | — | **2.52** | **2.23** | — | **4.51** | **2.69** | `suite-after-LH.json` — improved at H |
| `commit` | — | **0.84** | **0.48** | — | **1.16** | **0.70** | `commit-after-LH.json` — faster vs Git at L/H |
| `switch` | 3.29 | 3.44 | **2.94** | 4.89 | 5.63 | **4.06** | H improved; L still >2× |
| `switch-wide` | 3.70 | 2.29 | **3.42** | 26.5 | 2.98 | **22.54** | **H regression** — see refresh notes |
| `pick` | 1.41 | 1.14 | **1.48** | 5.50 | 4.04 | **5.22** | L slightly worse vs 2026-10-08 |
| `merge` | 2.61 | 2.18 | **2.86** | 3.97 | 3.83 | **3.74** | L ~32% worse ratio vs 2026-10-08 |
| `pick-series` | 12.9 | 11.2 | **11.94** | 21.7 | 17.7 | **18.56** | Still >2×; 20× `grit pick` vs one `git cherry-pick` range |
**2026-10-09 refresh vs 2026-10-08 baselines:** `grit-bench compare` reports ratio drift beyond the default **0.10** absolute tolerance on most scenarios (many improved). Regressions **more than 20% worse** on the Grit/Git ratio: **`switch-wide-100000`** (2.98× → **22.54×**), **`switch-wide-10000`** (2.29× → 3.42×), **`merge-10000`**, **`pick-10000`**, **`pick-100000`**. **`status-dirty-100000`** remains ~**53×** (unchanged). Suite **status** and **add** ratios improved at L/H except dirty-100k.
| Scenario | Git ms | Grit ms | Old ratio | New ratio |
| --- | ---: | ---: | ---: | ---: |
| `status-dirty-10000` | 11.1 | 80.1 | 10.19× | 7.21× |
| `status-dirty-100000` | 113.0 | 5962.1 | 52.66× | 52.77× |
| `status-clean-10000` | 9.0 | 21.2 | 4.58× | 2.34× |
| `status-clean-100000` | 82.7 | 513.8 | 9.67× | 6.21× |
| `add-10000` | 21.4 | 47.8 | 2.52× | 2.23× |
| `add-100000` | 224.8 | 603.6 | 4.51× | 2.69× |
| `commit-10000` | 165.6 | 79.1 | 0.84× | 0.48× |
| `commit-100000` | 1665.7 | 1159.3 | 1.16× | 0.70× |
| `switch-10000` | 23.9 | 70.3 | 3.44× | 2.94× |
| `switch-100000` | 160.6 | 652.4 | 5.63× | 4.06× |
| `switch-wide-10000` | 45.3 | 155.3 | 2.29× | 3.42× |
| `switch-wide-100000` | 386.4 | 8711.8 | 2.98× | 22.54× |
| `pick-10000` | 115.9 | 171.5 | 1.14× | 1.48× |
| `pick-100000` | 194.0 | 1011.6 | 4.04× | 5.22× |
| `merge-10000` | 104.9 | 300.5 | 2.18× | 2.86× |
| `merge-100000` | 283.4 | 1060.6 | 3.83× | 3.74× |
| `pick-series-10000` | 129.4 | 1544.3 | 11.18× | 11.94× |
| `pick-series-100000` | 961.6 | 17843.4 | 17.65× | 18.56× |
**Suite at L/H** (`grit-utils/baselines/suite-after-LH.json`): status scenarios remain far above 2× (dirty/clean at 10k and 100k files).
**H/L acceptance (1.25× bar):** after-run medians fail the scaling check for **`switch`**, **`switch-wide`**, **`pick`**, **`merge`**, and **`pick-series`** (not only switch/pick/merge). **`commit`** and **`add`** at H are within 2× of Git but **`add`** at L/H both exceed 2× at 10k and 100k files.
Two back-to-back hot-path after runs (`hot-paths-after-run1.json` vs `run2.json`) agree within **10% relative** on every scenario except `merge-100000` and `pick-100000` (~**13–14%** relative spread). The default `grit-bench compare` tolerance is an **absolute** 0.10 on the ratio, which is tighter than ±10% relative for large ratios (e.g. pick-series).
### Follow-up tracking (step 386)
No GitHub issues were filed from this factory run (`file_bug_report` is dogfooding-only). Track these against roadmap item 4:
- **L >2×:** `switch`, `switch-wide`, `merge`, `pick-series`, `add` (10k and 100k), status at L/H.
- **H/L >1.25×:** `switch`, `switch-wide`, `pick`, `merge`, `pick-series`.
- **Repeatability:** second hot-path after-run drift on `merge-100000` and `pick-100000` (~13–14% relative).
- **CLI gaps:** `grep`, `rebase`, `reset`, `stash push` (deferrals documented above).
**Criterion** (`cargo bench -p grit-lib --bench hot_paths`, release): see factory run log — `apply_stash_L` ~52 ms median; `pick_2000_paths_L` ~621 ms (library merge/checkout path, not CLI).
### Roadmap commands without a `grit` engine yet
| Git command | Grit CLI | How the plan covers it |
| --- | --- | --- |
| `grep` | none | Deferred — no porcelain driver in scope |
| `rebase` | none | `pick-series` grit-bench scenario (20× `grit pick`) as upper-bound proxy |
| `reset` | none | Deferred |
| `stash push` | none | Criterion `apply_stash` / library `apply_stash` bench; no `grit stash push` timing |
### Object reads
The **`grit-bench odb`** suite (library drivers in `grit-bench drive …` vs system **`git`**) measures cat-file batch reads, `rev-list --objects --all`, and `log -p` on a cached bare **git.git** clone and a repacked **100k-file / 1000-commit** synthetic repo. JSON reports include **peak RSS** per scenario (each workload measured in a fresh `grit-bench measure-rss` helper process via `getrusage(RUSAGE_CHILDREN)` on that run only) alongside wall time.
The **`grit-bench refs`** suite compares library drivers (`grit-bench refs-driver …`) to **`git for-each-ref`** and **`git update-ref --stdin`** on bare repositories with **100 000** branch refs. Fixtures are built once with system git and cached under the bench scratch directory: fully **packed** refs, **loose** refs only, and (when system git is **≥ 2.45**) a **reftable** layout. Scenarios list all refs, list the **`refs/heads/b05*`** glob (~1 000 refs), batch-**create** 100 000 refs into an empty-refs working copy, **update** 1 000 existing refs, and **delete** 1 000 refs; a prepare hook restores the fixture before each timed iteration. The committed baseline is **`grit-utils/baselines/refs-after.json`** (files-backend listing and batch `update-ref` optimizations on the 100k-ref fixtures).
```bash
cargo build --release -p grit-cli -p grit-utils
GRIT_BENCH_BRANCH=factory/files-refs-perf-782 ./target/release/grit-bench refs --format json --output grit-utils/baselines/refs-after.json
```
Set `GRIT_BENCH_BRANCH` to the GitButler branch you are benchmarking so `grit_commit` in the JSON matches that branch tip (required on `gitbutler/workspace` checkouts).
Driver **`for-each-ref`** output is checked against git byte-for-byte in `grit-utils` integration tests (1 000-ref fixture).
## grit-bench: network (clone, fetch, push, ls-remote)
The **`grit-bench network`** suite compares **`grit`** and system **`git`** on the same remote URLs. Cached fixtures live under **`GRIT_BENCH_NETWORK_CACHE`** (default `/tmp/grit-bench-network-cache`):
| Fixture | Shape |
| --- | --- |
| **deep-history** | **≥50 000** commits and **≥20 000** tracked files (built once via `git fast-import`) |
| **many-refs** | deep-history plus **≥10 000** `refs/heads/bench-ref-*` branches |
| **large-blobs** | a small tree with multi‑MiB blobs for pack-heavy transfer |
Scenarios include **clone** over **`file://`**, **git http-backend** (local CGI), and **grit-http-server** smart HTTP; **incremental** and **no-op fetch** over all three transports; **push** over **`file://`** and **grit-http-server** (git http-backend push is omitted until the bench CGI harness supports receive-pack); **`git ls-remote`** vs **`grit remote refs`** on the many-refs fixture over all three transports; and a **server-side** comparison that times system **`git clone`** against **git http-backend** vs **grit-http-server** on the same published bare repo. Hermetic git config matches other suites (`GIT_CONFIG_NOSYSTEM`, empty global config).
```bash
cargo build --release -p grit-cli -p grit-http-server -p grit-utils
./target/release/grit-bench network --format json --output grit-utils/baselines/network.json
./target/release/grit-bench compare grit-utils/baselines/network.json /tmp/network-rerun.json --tolerance 0.10
make docs
```
Integration smoke (tiny fixtures, fifteen scenarios; requires **hyperfine** on `PATH`): `cargo test -p grit-utils network_scenario_smoke_end_to_end`.
Acceptance bars for the network performance pass are **≤1.2×** git wall time on client-side scenarios (clone, fetch, push, ls-remote over `file://` and smart HTTP). Compare the generated table ratios to that bar.
**Server-side clone (`server-clone-http-compare-*`):** system **`git clone`** against **grit-http-server** is expected to stay above **1.2×** until the upload-pack path uses **reachability bitmaps** during negotiation (same dependency as Git’s `upload-pack` on large, pack-served repos). Client-side grit and git both pay similar pack transfer cost; the gap is dominated by grit’s in-process upload-pack enumeration without bitmaps, not HTTP keep-alive or side-band framing. Track under the MIDX/bitmap roadmap item rather than masking with compatibility shortcuts.
Regenerate release binaries with **`cargo build --release -p grit-lib`** before **`grit-bench network`** so the timed **`grit`** binary includes library changes.
### Results
| | |
| --- | --- |
| Git | git version 2.43.0 |
| Grit | grit 0.5.3 |
| CPU | Intel(R) Xeon(R) Processor |
| OS | linux (Linux 6.12.94+) |
| Recorded | 2026-10-09 07:45:00.292685959 |
## Summary by operation
| Operation | Scenarios | Median Grit / Git | Worst Grit / Git |
| --- | ---: | ---: | ---: |
| add | 2 | 2.56× | 2.59× |
| bitmaps | 3 | 17.93× | 63.72× |
| commit | 2 | 0.58× | 0.68× |
| delta_encode | 2 | — | — |
| merge | 2 | 3.40× | 3.84× |
| network-clone | 3 | 2.41× | 2.82× |
| network-fetch | 6 | 0.84× | 2.83× |
| network-ls-remote | 3 | 1.29× | 1.98× |
| network-push | 2 | 8.44× | 16.20× |
| network-server | 1 | 42.44× | 42.44× |
| object_reads | 8 | 234.49× | 4569.02× |
| odb_backend | 6 | 14.90× | 98.20× |
| pick | 4 | 8.63× | 17.09× |
| refs | 10 | 0.84× | 1.95× |
| status | 4 | 6.17× | 48.09× |
| switch | 4 | 3.61× | 22.50× |
### add
| Scenario | Fixture | Git mean (ms) | Grit mean (ms) | Grit / Git | Spread |
| --- | --- | ---: | ---: | ---: | --- |
| `add-10000` | synthetic-10000 | 21.8 | 55.2 | 2.53× | ±32.9 ms |
| `add-100000` | synthetic-100000 | 234 | 608 | 2.59× | ±45.7 ms |
### bitmaps
| Scenario | Fixture | Git mean (ms) | Grit mean (ms) | Grit / Git | Spread |
| --- | --- | ---: | ---: | ---: | --- |
| `clone-file-prod` | /tmp/grit-bench-network-cache/deep-history-prod.git | 546 | 1,537 | 2.82× | ±112 ms |
| `clone-git-http-prod` | /tmp/grit-bench-network-cache/deep-history-prod.git | 787 | 1,893 | 2.41× | ±160 ms |
| `clone-grit-http-prod` | /tmp/grit-bench-network-cache/deep-history-prod.git | 19,584 | 19,893 | 1.02× | ±1,150 ms |
| `rev-list-count-git.git` | git.git | 57.7 | 1,034 | 17.93× | ±4.35 ms |
| `rev-list-count-objects-git.git` | git.git | 17.0 | 1,082 | 63.72× | ±55.0 ms |
| `serve-clone-git.git` | git.git | 682 | 0.00 | 0.00× | ±0.00 ms |
### network-fetch
| Scenario | Fixture | Git mean (ms) | Grit mean (ms) | Grit / Git | Spread |
| --- | --- | ---: | ---: | ---: | --- |
| `fetch-incr-file-prod` | /tmp/grit-bench-network-cache/deep-history-prod.git | 74.7 | 55.3 | 0.74× | ±3.44 ms |
| `fetch-incr-git-http-prod` | /tmp/grit-bench-network-cache/deep-history-prod.git | 98.0 | 100 | 1.02× | ±7.40 ms |
| `fetch-incr-grit-http-prod` | /tmp/grit-bench-network-cache/deep-history-prod.git | 891 | 834 | 0.94× | ±65.8 ms |
| `fetch-noop-file-prod` | /tmp/grit-bench-network-cache/deep-history-prod.git | 12.9 | 36.5 | 2.83× | ±2.36 ms |
| `fetch-noop-git-http-prod` | /tmp/grit-bench-network-cache/deep-history-prod.git | 23.6 | 17.0 | 0.72× | ±1.42 ms |
| `fetch-noop-grit-http-prod` | /tmp/grit-bench-network-cache/deep-history-prod.git | 25.6 | 15.9 | 0.62× | ±1.18 ms |
### network-ls-remote
| Scenario | Fixture | Git mean (ms) | Grit mean (ms) | Grit / Git | Spread |
| --- | --- | ---: | ---: | ---: | --- |
| `ls-remote-file-prod` | /tmp/grit-bench-network-cache/many-refs-prod.git | 51.1 | 101 | 1.98× | ±10.5 ms |
| `ls-remote-git-http-prod` | /tmp/grit-bench-network-cache/many-refs-prod.git | 20.1 | 25.1 | 1.25× | ±1.65 ms |
| `ls-remote-grit-http-prod` | /tmp/grit-bench-network-cache/many-refs-prod.git | 75.9 | 98.1 | 1.29× | ±24.3 ms |
### delta_encode
| Scenario | Fixture | Git mean (ms) | Grit mean (ms) | Grit / Git | Spread |
| --- | --- | ---: | ---: | ---: | --- |
| `push-file-prod` | /tmp/grit-bench-network-cache/deep-history-prod.git | 39.5 | 26.6 | 0.68× | ±1.91 ms |
| `push-grit-http-prod` | /tmp/grit-bench-network-cache/deep-history-prod.git | 47.5 | 770 | 16.20× | ±59.6 ms |
### merge
| Scenario | Fixture | Git mean (ms) | Grit mean (ms) | Grit / Git | Spread |
| --- | --- | ---: | ---: | ---: | --- |
| `server-clone-http-compare-prod` | /tmp/grit-bench-network-cache/deep-history-prod.git | 609 | 25,829 | 42.44× | ±3,884 ms |
### object_reads
| Scenario | Fixture | Git mean (ms) | Grit mean (ms) | Grit / Git | Spread |
| --- | --- | ---: | ---: | ---: | --- |
| `cat-file-batch-sorted-git.git` | git.git | 32,433 | 46,558 | 1.44× | ±253 ms |
| `cat-file-batch-unordered-git.git` | git.git | 10,655 | 15,384 | 1.44× | ±62.4 ms |
| `log-patch-2000-git.git` | git.git | 1,518 | 699,640 | 460.95× | ±15,497 ms |
| `rev-list-objects-git.git` | git.git | 3,036 | 1,590,307 | 523.82× | ±2,433 ms |
| `cat-file-batch-sorted-hot-path-100k` | hot-path-100k | 119 | 922 | 7.76× | ±2.48 ms |
| `cat-file-batch-unordered-hot-path-100k` | hot-path-100k | 117 | 937 | 8.03× | ±28.4 ms |
| `log-patch-2000-hot-path-100k` | hot-path-100k | 400 | 1,827,664 | 4569.02× | ±12,342 ms |
| `rev-list-objects-hot-path-100k` | hot-path-100k | 55.4 | 34,028 | 614.25× | ±43.8 ms |
### odb_backend
| Scenario | Fixture | Git mean (ms) | Grit mean (ms) | Grit / Git | Spread |
| --- | --- | ---: | ---: | ---: | --- |
| `cat-file-batch-check-hot-path-100k` | hot-path-100k | 46.8 | 246 | 5.26× | ±17.0 ms |
| `cat-file-batch-check-hot-path-100k-pre-refactor` | hot-path-100k | 56.7 | 1,298 | 22.88× | ±196 ms |
| `cat-file-batch-hot-path-100k` | hot-path-100k | 150 | 354 | 2.36× | ±9.24 ms |
| `cat-file-batch-hot-path-100k-pre-refactor` | hot-path-100k | 162 | 1,117 | 6.91× | ±19.5 ms |
| `rev-list-objects-odb-backend-hot-path-100k` | hot-path-100k | 66.2 | 6,242 | 94.23× | ±121 ms |
| `rev-list-objects-odb-backend-hot-path-100k-pre-refactor` | hot-path-100k | 71.9 | 7,062 | 98.20× | ±446 ms |
### pick
| Scenario | Fixture | Git mean (ms) | Grit mean (ms) | Grit / Git | Spread |
| --- | --- | ---: | ---: | ---: | --- |
| `pick-10000` | synthetic-10000 | 117 | 171 | 1.46× | ±4.25 ms |
| `pick-series-10000` | synthetic-10000 | 129 | 1,551 | 11.98× | ±64.2 ms |
| `pick-100000` | synthetic-100000 | 194 | 1,021 | 5.27× | ±48.8 ms |
| `pick-series-100000` | synthetic-100000 | 1,045 | 17,861 | 17.09× | ±426 ms |
### refs
| Scenario | Fixture | Git mean (ms) | Grit mean (ms) | Grit / Git | Spread |
| --- | --- | ---: | ---: | ---: | --- |
| `for-each-ref-all-refs-100k-loose` | refs-100k-loose | 1,732 | 1,225 | 0.71× | ±35.8 ms |
| `for-each-ref-prefix-b05-refs-100k-loose` | refs-100k-loose | 550 | 173 | 0.31× | ±10.3 ms |
| `update-ref-create-100k-refs-100k-loose` | refs-100k-loose | 4,435 | 2,925 | 0.66× | ±91.6 ms |
| `update-ref-delete-1k-refs-100k-loose` | refs-100k-loose | 50.5 | 59.9 | 1.19× | ±3.65 ms |
| `update-ref-update-1k-refs-100k-loose` | refs-100k-loose | 77.2 | 68.8 | 0.89× | ±4.93 ms |
| `for-each-ref-all-refs-100k-packed` | refs-100k-packed | 1,219 | 729 | 0.60× | ±41.1 ms |
| `for-each-ref-prefix-b05-refs-100k-packed` | refs-100k-packed | 12.8 | 15.8 | 1.24× | ±1.88 ms |
| `update-ref-create-100k-refs-100k-packed` | refs-100k-packed | 4,799 | 3,765 | 0.78× | ±212 ms |
| `update-ref-delete-1k-refs-100k-packed` | refs-100k-packed | 69.0 | 99.5 | 1.44× | ±34.7 ms |
| `update-ref-update-1k-refs-100k-packed` | refs-100k-packed | 62.8 | 122 | 1.95× | ±41.2 ms |
### status
| Scenario | Fixture | Git mean (ms) | Grit mean (ms) | Grit / Git | Spread |
| --- | --- | ---: | ---: | ---: | --- |
| `status-clean-10000` | synthetic-10000 | 9.79 | 21.7 | 2.22× | ±2.13 ms |
| `status-dirty-10000` | synthetic-10000 | 11.5 | 81.1 | 7.04× | ±5.29 ms |
| `status-clean-100000` | synthetic-100000 | 95.6 | 506 | 5.29× | ±26.6 ms |
| `status-dirty-100000` | synthetic-100000 | 125 | 6,011 | 48.09× | ±274 ms |
### switch
| Scenario | Fixture | Git mean (ms) | Grit mean (ms) | Grit / Git | Spread |
| --- | --- | ---: | ---: | ---: | --- |
| `switch-10000` | synthetic-10000 | 24.6 | 70.5 | 2.86× | ±2.28 ms |
| `switch-wide-10000` | synthetic-10000 | 46.6 | 158 | 3.38× | ±6.96 ms |
| `switch-100000` | synthetic-100000 | 172 | 658 | 3.83× | ±20.5 ms |
| `switch-wide-100000` | synthetic-100000 | 389 | 8,763 | 22.50× | ±179 ms |
To refresh this page after updating a baseline JSON file, regenerate the static site:
```bash
make docs
```
The docs `--check` step fails if baseline numbers change without re-running `make docs`.
For other library surfaces under test, see the [grit-lib API on docs.rs](https://docs.rs/grit-lib).
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

