Programmatic git operations built on @catmint-fs/core layers. Implements git plumbing and porcelain in pure TypeScript with no native dependencies, producing repositories that are fully compatible with the canonical git CLI.
- Pure TypeScript -- no shelling out to
git, no native bindings - Browser-compatible -- uses Web Crypto for SHA-1,
Uint8Arrayfor binary data,fetch()for HTTP transport - Adapter-agnostic -- works with any
@catmint-fs/coreadapter (in-memory, local disk, SQLite, custom) - Git-CLI compatible -- repositories created by this library are readable by
git log,git status,git branch, etc., and vice versa - Full lifecycle -- init, commit, log, branch, checkout, merge (with conflict detection), tag, stash, diff, reset, remote, fetch, push, pull, clone
pnpm add @catmint-fs/git @catmint-fs/coreimport { createLayer } from "@catmint-fs/core";
import { initRepository } from "@catmint-fs/git";
const layer = await createLayer({ root: "/tmp/my-repo" });
const repo = await initRepository(layer);
// Create and commit a file
await layer.writeFile("/hello.txt", "Hello, world!\n");
await repo.add("/hello.txt");
const oid = await repo.commit({
message: "initial commit",
author: { name: "Alice", email: "alice@example.com" },
});
// Read the log
const commits = await repo.log();
console.log(commits[0].message); // "initial commit"// Initialize a new repository
initRepository(layer: Layer, options?: InitOptions): Promise<Repository>
// Open an existing repository
openRepository(layer: Layer): Promise<Repository>
// Clone a remote repository
cloneRepository(layer: Layer, options: CloneOptions): Promise<Repository>
// Create an HTTP transport
httpTransport(options?: HttpTransportOptions): HttpTransportrepo.currentBranch(): Promise<string | null>
repo.createBranch(name, options?): Promise<void>
repo.deleteBranch(name, options?): Promise<void>
repo.listBranches(options?): Promise<BranchInfo[]>
repo.renameBranch(oldName, newName): Promise<void>
repo.checkout(ref, options?): Promise<void>repo.add(pathOrPaths): Promise<void>
repo.unstage(pathOrPaths): Promise<void>
repo.remove(pathOrPaths, options?): Promise<void>
repo.status(path?): Promise<StatusEntry[]>
repo.listFiles(): Promise<string[]>
repo.isIgnored(path): Promise<boolean>repo.commit(options): Promise<string> // returns commit OID
repo.log(options?): Promise<CommitInfo[]>
repo.readCommit(oid): Promise<CommitInfo>repo.merge(ref, options?): Promise<MergeResult>
repo.abortMerge(): Promise<void>merge() supports fast-forward, merge commits, and conflict detection. When conflicts arise, the result contains conflict markers and the conflicted paths.
repo.createTag(name, options?): Promise<void> // lightweight or annotated
repo.deleteTag(name): Promise<void>
repo.listTags(): Promise<TagInfo[]>repo.diff(options?): Promise<DiffResult>By default, diffs the working tree against the index. Pass { staged: true } to diff the index against HEAD.
repo.stash(options?): Promise<void>
repo.listStashes(): Promise<StashEntry[]>
repo.applyStash(options?): Promise<void>
repo.popStash(options?): Promise<void>
repo.dropStash(index?): Promise<void>repo.reset(ref, options?): Promise<void>Supports soft, mixed (default), and hard modes, as well as path-specific resets.
repo.addRemote(name, url): Promise<void>
repo.listRemotes(): Promise<RemoteInfo[]>
repo.deleteRemote(name): Promise<void>
repo.setUpstream(branch, upstream): Promise<void>
repo.fetch(remote, options?): Promise<FetchResult>
repo.push(remote, options?): Promise<PushResult>
repo.pull(remote, options?): Promise<MergeResult>repo.getConfig(key): Promise<string | null>
repo.setConfig(key, value): Promise<void>
repo.deleteConfig(key): Promise<void>repo.resolveRef(ref): Promise<string> // returns OID
repo.listRefs(prefix?): Promise<RefEntry[]>For advanced use cases, the internals are also exported:
| Export | Description |
|---|---|
ObjectDB |
Read/write loose git objects (blobs, trees, commits, tags) |
RefStore |
Manage loose refs, symbolic refs, and packed-refs |
IndexFile |
Parse and serialize the git index (binary format v2) |
GitConfig |
Read/write git config files |
GitIgnore |
Evaluate .gitignore patterns |
DiffEngine |
Compute file-level and hunk-level diffs |
MergeEngine |
Three-way merge with conflict detection |
StashManager |
Stash save/apply/pop/drop operations |
HttpTransport |
Smart HTTP transport for fetch/push |
computeDiffHunks |
Standalone function for line-level diff computation |
import { createLayer } from "@catmint-fs/core";
import { SqliteAdapter } from "@catmint-fs/sqlite-adapter";
import { initRepository } from "@catmint-fs/git";
const adapter = new SqliteAdapter({ database: ":memory:" });
const layer = await createLayer({ root: "/", adapter });
const repo = await initRepository(layer);
// ... use repo normallyRepositories produced by this library are valid git repositories. You can verify with the standard git CLI:
cd /tmp/my-repo
git log --oneline
git status
git branch -a
git tag -lConversely, repositories created by the git CLI can be opened with openRepository().
GPL-2.0 -- see LICENSE for details.