Core Concepts
type-git is designed with type safety first. This page explains the key concepts that make type-git different from other git libraries.
Type Safety Philosophy
type-git provides strong type guarantees at every level:
// Every operation returns typed resultsconst status = await repo.status();// status.entries is typed as PorcelainV2Entry[]
const commits = await repo.log({ maxCount: 10 });// commits is typed as Commit[]
const branches = await repo.branch.list();// branches is typed as BranchInfo[]No any types. Every return value, every option, every error is fully typed.
Three-Layer API
type-git provides three levels of abstraction:
1. Raw API
Direct access to git commands with unprocessed output:
const result = await repo.raw(['log', '--oneline', '-5']);// Returns { stdout: string, stderr: string, exitCode: number }Use when:
- Output isn’t covered by typed APIs
- You want to process output yourself
- Running custom git commands
2. Typed API
Parsed, type-safe output for common operations:
const status = await repo.status();for (const entry of status.entries) { console.log(entry.path, entry.index, entry.workdir);}Use when:
- You want structured data
- You need type safety
- Output format is predictable
3. High-Level API
Convenience methods for common workflows:
await repo.branch.create('feature-x');await repo.stash.push({ message: 'WIP' });await repo.tag.create('v1.0.0', { message: 'Release' });Use when:
- You want a clean, intuitive API
- Doing common git operations
Context Separation
type-git separates operations into two contexts:
Git (Repository-Agnostic)
Operations that don’t require a repository:
const git = new TypeGit();
await git.clone(url, path); // Clone remote repoawait git.init(path); // Create new repoawait git.lsRemote(url); // List remote refsawait git.version(); // Get git versionRepo (Repository-Specific)
Operations that require a repository context:
const repo = await git.open('./my-repo');
await repo.status();await repo.commit({ message: 'feat: add feature' });await repo.push();This separation ensures you can’t accidentally call repository-specific operations without a valid repository context.
Repository Opening
type-git provides three ways to open repositories with different type guarantees:
open() - Worktree Repository
The most common use case. Returns a WorktreeRepo type:
const repo = await git.open('./my-repo');// repo is WorktreeRepo - full access to status(), commit(), etc.
// Throws GitError with kind 'NotWorktreeRepo' if the repo is bareopenBare() - Bare Repository
For server-side or backup repositories. Returns a BareRepo type:
const bareRepo = await git.openBare('./my-repo.git');// bareRepo is BareRepo - limited to fetch(), push(), etc.
// Throws GitError with kind 'NotBareRepo' if the repo is not bareopenRaw() - Unknown Repository Type
When you don’t know the repository type at compile time:
const repo = await git.openRaw(path);// repo is WorktreeRepo | BareRepo
// Use type guards to narrow the typeif ('workdir' in repo) { // repo is WorktreeRepo await repo.status();} else { // repo is BareRepo await repo.fetch('origin');}Output Contract
type-git uses git’s porcelain and machine-readable output formats for reliable parsing:
| Operation | Format | Stability |
|---|---|---|
status() | --porcelain=v2 | Stable |
log() | Custom format string | Stable |
branch.list() | --format=%(...) | Stable |
lsRemote() | Tab-separated | Stable |
This means type-git’s parsing is:
- Predictable: Output format won’t change between git versions
- Reliable: No regex hacks on human-readable output
- Fast: Minimal parsing overhead
Error Handling
All git errors are wrapped in a typed GitError:
import { GitError } from 'type-git';
try { await repo.push();} catch (error) { if (error instanceof GitError) { console.log(error.kind); // 'NonZeroExit' | 'Aborted' | 'SpawnFailed' | ... console.log(error.category); // 'authentication' | 'network' | 'conflict' | ... console.log(error.exitCode); console.log(error.stderr); }}Error Kinds
| Kind | Description |
|---|---|
NonZeroExit | Git command exited with non-zero code |
Aborted | Operation was cancelled via AbortSignal |
SpawnFailed | Failed to spawn git process |
ParseError | Failed to parse git output |
NotWorktreeRepo | Expected worktree but found bare repository |
NotBareRepo | Expected bare but found worktree repository |
CapabilityMissing | Required capability is missing |
The category property provides semantic error classification, making it easy to handle specific error types.
Next Steps
- Quick Start - Get started with type-git
- Architecture - Understand the internal design