Git Integration Guide

Overview

GitBucket.WTF stores git repositories directly in object storage (S3-compatible, Vercel Blob, or local FS) — there's no relational database in the path. Both clients use a shared engine (@gitbucket/storage's GitEngine) so the on-disk layout is identical no matter which one wrote it.

Two client paths:

  1. HTTP Smart Protocol — standard git against the Next.js app. Use this when you want git clone https://.../git push to work unchanged.
  2. gib CLI — direct-to-bucket, no server. Use this for CI/CD, air-gapped setups, or platform-free workflows. See CLI.md.

Architecture

Storage Structure

Git objects are stored in the bucket following the standard Git object model:

{prefix}/                       # e.g. repos/{orgId}/{repoId}/ for the web app,
  ├── HEAD                      #      or any user-chosen path for gib
  ├── objects/
  │   ├── {hash[0:2]}/
  │   │   └── {hash[2:]}        # loose objects (header + content, no compression)
  │   └── pack/
  │       ├── pack-{sha}.pack   # downloaded by gib clone/pull
  │       └── pack-{sha}.idx
  ├── refs/
  │   ├── heads/
  │   │   └── {branchName} -> commit hash
  │   └── tags/
  │       └── {tagName} -> commit hash

HEAD is a symbolic ref (ref: refs/heads/<default-branch>\n) so the engine can determine the default branch without needing a separate config file.

Git HTTP Smart Protocol

GitBucket.WTF implements the Git HTTP Smart Protocol endpoints:

  1. Info/Refs (GET /api/git/:orgSlug/:repoSlug/info/refs?service=git-upload-pack)

    • Returns available refs (branches, tags)
    • Used by git clone and git fetch
  2. Upload Pack (POST /api/git/:orgSlug/:repoSlug/git-upload-pack) - TODO

    • Handles object transfer for clone/fetch operations
  3. Receive Pack (POST /api/git/:orgSlug/:repoSlug/git-receive-pack) - TODO

    • Handles object transfer for push operations

Usage

Path A — standard git over HTTPS (web app)

git clone https://gitbucket.wtf/api/git/myorg/myrepo.git
git remote add origin https://gitbucket.wtf/api/git/myorg/myrepo.git
git push origin main
git pull origin main

Path B — direct to bucket with gib

# From inside any git repo
gib remote add origin s3://my-bucket/repos/myorg/myrepo
gib push origin main
gib status                                # see what's ahead/behind
gib clone s3://my-bucket/repos/myorg/myrepo ./fresh-clone

See CLI.md for the full surface, storage URL formats, and the gib status state legend.

Configuration

Each organization configures its own S3/Storj credentials:

  1. Go to Organization Settings
  2. Configure S3 endpoint, bucket, region, and credentials
  3. All repositories under that organization use these credentials

Implementation Status

  • ✅ Shared GitEngine in @gitbucket/storage (one engine, two clients)
  • ✅ Pluggable storage adapters (S3-compatible, Vercel Blob, local FS)
  • ✅ Loose object + ref read/write
  • ✅ Pack data plane (storePack/listPacks/getPack) — CLI uses it on download
  • gib CLI: init, remote, push, pull, clone, status
  • ✅ Info/Refs / Upload Pack / Receive Pack HTTP smart-protocol routes
  • 🚧 Pack-on-push for the CLI (data plane ready; blocked on server-side pack reads)
  • 🚧 Server-side pack-aware reads in GitEngine.getObject (needed before pack-on-push is safe)

Future Enhancements

  • SSH support
  • Web hooks
  • Branch protection rules enforcement
  • Large file support (Git LFS)
  • Shallow clone support