The tree-sha256 digest hashes file and submodule contents with SHA-256 (not Git's SHA-1 object names). Grit exposes it on Repository::tree_sha256.
Compute a digest
use grit_lib::repo::{InitOptions, Repository};
use grit_lib::tree_sha256::TreeSha256Options;
let dir = tempfile::tempdir()?;
let repo = Repository::init(dir.path(), &InitOptions::default())?;
let report = repo.tree_sha256(head, &TreeSha256Options::default())?;
println!("{}", report.digest);
TreeSha256Report includes counts and any submodule paths recorded as cycle: or excluded: (see the upstream spec).
Missing submodules
When a gitlink submodule is not checked out or its commit is absent, hashing returns Error::TreeSha256MissingSubmodules listing every path.
Tag header claim
Annotated tags can carry a TreeSha256Claim in extra headers (immediately after tagger, before any other custom headers):
- one
tree-sha256-excluded <path>line per excluded submodule (sorted when written) - one
tree-sha256 <64-hex>line with exactly 64 hex digits (no surrounding whitespace)
Read a claim with TreeSha256Claim::from_tag on TagData, or attach one with TreeSha256Claim::apply_to_tag. Header names are TREE_SHA256_HEADER and TREE_SHA256_EXCLUDED_HEADER.
Excluded paths in TreeSha256Claim::excluded must be non-empty and must not contain NUL or newline when calling apply_to_tag (the same rules enforced when reading tags).
Verify a signed tag
Repository::verify_tag reads an annotated tag object by id (not via a ref), checks its appended signature with TagVerifyOptions::gpg, and recomputes the tree-sha256 claim when the header is present. Signature verification and digest hashing run on separate threads.
Excluded submodule paths recorded in tree-sha256-excluded headers are hashed with TreeSha256Options::exclude_exact only (no globs). Paths that are not gitlinks in the tagged tree are reported in TreeSha256Verdict::bogus_excluded and fail TagVerification::is_ok. Real excluded submodules are listed in TreeSha256Verdict::excluded but do not fail verification.
use grit_lib::commit::signing::GpgConfig;
use grit_lib::repo::Repository;
use grit_lib::tree_sha256::TagVerifyOptions;
let gpg = GpgConfig::from_config(repo.config()?.as_ref())?
.with_command_runner(repo.command_runner());
let report = repo.verify_tag(tag_oid, &TagVerifyOptions {
check_signature: true,
gpg,
})?;
assert!(report.is_ok());
To verify by tag name, as grit tag --verify does, call verify_tag_by_name. It resolves refs/tags/<name> through the repository's ref store (loose, packed or reftable), reads the tag object once, and returns a VerifiedTag with the tag object id, the object header target and the TagVerification. A bad name, a missing tag, and a lightweight tag (one with no tag object to verify) are the typed errors TagError::InvalidName, TagError::NotFound and TagError::Lightweight.