Branches
listBranches, createBranchFrom, deleteBranchByName,
assertBranchExists. See
Branches & commits.
git-fs-s3/ops is the layer a repo browser, a PR flow, or a
CMS admin UI actually needs — branches, commit writing, tree read/write,
commit history, file history, diffs, and merge — built entirely on the root
package’s createGitFs. Extracted from a production git-hosting service’s
own application layer.
Branches
listBranches, createBranchFrom, deleteBranchByName,
assertBranchExists. See
Branches & commits.
Commits
commitFilesToBare, deleteFileFromBare, writeCommitToBare,
authorNow. See
Branches & commits.
Trees, history & diff
Tree primitives, cached commit-log walks, file history, diffs. See Trees, history & diff.
Merge
Fast-forward and pre-merge analysis. See Merge.
OpsHooks: the shared seamEvery function in this module accepts an optional hooks: OpsHooks as its
last argument:
interface OpsHooks { resultCache?: ResultCache; /** Wrap a timed sub-step (network walk, tree listing). Default: run directly. */ step?<T>(label: string, fn: () => Promise<T>): Promise<T>; /** Diagnostic sink for cache hit/miss and walk summaries. */ onNote?(message: string): void; /** * Called once before history walks of depth >= prefetchMinDepth — wire * pack prefetching (e.g. GitFs.prefetchPacks) here. */ prefetch?(): Promise<void>; /** Minimum walk depth before `prefetch` fires. Default 5. */ prefetchMinDepth?: number;}A typical wiring, reused across every call:
const hooks: OpsHooks = { resultCache: myAppResultCache, // see ResultCache below step: perfStep, onNote: (msg) => console.debug(msg), prefetch: () => (repo.fs as GitFs).prefetchPacks(repo.gitdir), prefetchMinDepth: 5,};ResultCacheSeveral functions in this module — getCommitLog, getTreeFromRef,
getCommitHistory, getLastCommitsForTree, getFileHistory — memoize
expensive walk results (a commit log, a tree listing) so repeated or
overlapping requests don’t re-walk from scratch:
interface ResultCache { get<T>(key: string): T | null | undefined; set(key: string, value: unknown): void;}Keys are namespaced <kind>:<gitdir>:..., so entries self-invalidate on a
new push (a new head sha means a new key) — but you still need to evict
entries under resultKeyPrefixes(gitdir)
after rewriting a repo’s storage out of band (a bulk sync, a rename), or a
stale walk outlives the history it describes.
Any object satisfying the two-method interface works — an LRU, a Map, a
Redis client wrapper. get/set are called with plain values (arrays,
objects); the store owns how it actually keeps them.
Every function takes a Repo as its first argument — the same shape
createGitFs produces:
interface Repo { fs: IsoGitFs; gitdir: string; cache?: object; // isomorphic-git's own shared parse cache — recommended per repo}Create one per request and reuse it across every /ops call in that
request — sharing cache is what lets isomorphic-git reuse parsed pack
indexes instead of re-parsing them on every call.