gitcaskDocsGitHub

Initialize and import

Start a pristine repository from one pinned tree, or from another repository's full history, committed by the same manifest compare-and-swap as a push.

Which one

Both write into an existing, pristine destination and copy every object into its own packs.

InitializeImport
CreatesOne new parentless commit on one branch, with HEAD pointing at itEvery head and tag, and HEAD (symbolic or detached), with their full reachable history
SourceA full commit OID in another gitcask repositoryA gitcask repository, or a public HTTPS Git URL
HistoryNone: only the source tree is copiedAll of it, unchanged
Commit contentMessage, author and committer supplied by the callerThe source objects as they are

Initialize from a pinned tree

The caller pins a full commit OID, not a branch. Its tree is uploaded into the destination's wal/ before the manifest CAS publishes the new commit.

pinned commit_oid
upload tree closure to wal/
CAS manifest.pb
201
Pinned source commit, then its tree closure uploaded to the destination wal, then the manifest compare-and-swap, then 201.
POST /{owner}/{repo}/api/initialize
{
  "source": {"owner": "templates", "repo": "starter", "commit_oid": "0123456789012345678901234567890123456789"},
  "branch": "main",
  "operation_key": "project-creation-7",
  "message": "Initial project",
  "committer": {"name": "Project Builder", "email": "builder@example.test", "when": "2026-09-28T00:00:00Z"}
}
201 Created
{"ref":"refs/heads/main","commit_oid":"<new root oid>","tree_oid":"<source tree oid>","seq":1,"replayed":false}

Import a full history

Resolve pins the source refs into a snapshot. Your platform persists it, then imports exactly that snapshot.

POST api/import/resolve
persist the snapshot
POST api/import
CAS manifest.pb
201
Resolve, then the platform persists the snapshot, then import, then the manifest compare-and-swap, then 201.

Resolve

POST /{owner}/{repo}/api/import/resolve
{"source":"templates/starter"}
200 OK
{"source":"templates/starter","object_format":"sha1","refs":[{"name":"refs/heads/develop","oid":"<full lower-case oid>","peeled":""}],"head":{"symbolic_target":"refs/heads/develop","oid":"<full lower-case oid>"},"snapshot_hash":"<sha256>"}

Import

POST /{owner}/{repo}/api/import
{"operation_key":"creation-123","snapshot":{"source":"templates/starter","object_format":"sha1","refs":[{"name":"refs/heads/develop","oid":"<full lower-case oid>","peeled":""}],"head":{"symbolic_target":"refs/heads/develop","oid":"<full lower-case oid>"},"snapshot_hash":"<sha256>"}}
201 Created
{"operation_key":"creation-123","request_hash":"<sha256>","snapshot_hash":"<sha256>","seq":1,"refs_count":1,"head":{"symbolic_target":"refs/heads/develop","oid":"<original oid>"},"replayed":false}

Endpoints and retries

Repeat the identical request to retry. An exact replay returns the original result with replayed:true and never opens the source or moves a ref.

EndpointBody limitAnswers
POST /{owner}/{repo}/api/initialize64 KiB201 first, 200 exact replay
POST /{owner}/{repo}/api/import/resolve4 KiB200 snapshot; resolve again if lost before persisting
POST /{owner}/{repo}/api/import1 MiB201 first, 200 exact replay
GET /{owner}/{repo}/api/import/receipt?operation_key=…&request_hash=…No body200 with replayed:true, 404 absent, 409 key or hash mismatch
operation_key
1–128 printable ASCII characters without whitespace.
Receipt
One bounded receipt, committed in the same manifest CAS, records the operation key, the request fingerprint and the original result.
Permissions
Every attempt, replays included, needs destination write and source read. The receipt GET needs only target read.
Pristine
No committed WAL work, packs, checkpoint or receipt. A repository whose refs were all deleted is not pristine.
Streaming
With Accept: text/event-stream, work streams as a task with progress; the HTTP status is 200 and the terminal packet carries the result or error.

Boundaries and bounds

Object format
SHA-1 and SHA-256 between gitcask repositories; source and target must match (400 otherwise).
Git LFS
Any recognized LFS pointer is rejected with 422 before publication. Import checks every historical small blob, not only the tip.
Gitlinks
Copied unchanged; submodules are never fetched or recursed.
External import
Public HTTPS on port 443, SHA-1 only, no credentials, query or fragment. DNS is pinned to public addresses and every redirect is refused.
[import] keyDefaultBounds
max_refs1024Heads and tags per snapshot
max_objects1000000Acquired historical objects
max_bytes"1 GiB"External response bytes and output pack; also server.max_push_bytes
resolve_timeout"30s"Refs and HEAD acquisition
timeout"15m"Bulk acquisition and validation, before the CAS

Errors

Non-503 errors are plain text. A 503 is retryable JSON with Retry-After: retry the identical request.

Initialize

StatusMeaning
400Invalid request/identity/branch/full commit ID, non-commit source object, or different object formats
401Missing or invalid credentials
403Write denied by the existing forwarded-identity contract
404Missing or unauthorized repository, or unavailable pinned source commit
409Destination is not pristine, or a committed initializer has a different operation key or fingerprint
413Request body or configured server.max_push_bytes pack limit exceeded
422Source tree contains a Git LFS pointer; this operation does not copy LFS payloads
503Temporary object-store/authentication-service failure; retry the identical request

Import

StatusMeaning
400Invalid snapshot/hash/format/source URL or unsafe DNS result
401 / 403 / 404Existing auth/permission/missing-repository contract
409Nonpristine, operation conflict, or pinned source unavailable
413JSON, refs, transfer, output pack or object bound exceeded
422Empty/unborn source, LFS pointer history, or source requiring auth/redirect/dumb HTTP
503Resolve busy, deadline, source DNS/transport, store/auth failure or drain; retry fixed request