mirror of
https://github.com/KohakuBlueleaf/KohakuHub.git
synced 2026-05-08 12:57:36 -05:00
408 lines
8.0 KiB
Markdown
408 lines
8.0 KiB
Markdown
---
|
|
title: Git Protocol API
|
|
description: Git Smart HTTP and SSH support for clone/push/pull operations
|
|
icon: i-carbon-code
|
|
---
|
|
|
|
# Git Protocol API
|
|
|
|
KohakuHub implements Git Smart HTTP protocol for seamless `git clone`, `git push`, and `git pull` operations.
|
|
|
|
---
|
|
|
|
## Git Smart HTTP
|
|
|
|
### Service Advertisement
|
|
|
|
**Pattern:** `GET /{namespace}/{name}.git/info/refs?service={service}`
|
|
|
|
**Path Parameters:**
|
|
- `namespace`: User or organization name
|
|
- `name`: Repository name
|
|
|
|
**Query Parameters:**
|
|
- `service`: `git-upload-pack` (clone/fetch) or `git-receive-pack` (push)
|
|
|
|
**Authentication:**
|
|
- Optional for `git-upload-pack` (public repos)
|
|
- Required for `git-receive-pack` (push operations)
|
|
- Uses HTTP Basic Auth with token as password
|
|
|
|
**Response:**
|
|
```
|
|
001e# service=git-upload-pack
|
|
0000
|
|
<pkt-line formatted capabilities>
|
|
```
|
|
|
|
**Headers:**
|
|
- `Content-Type`: `application/x-git-upload-pack-advertisement` or `application/x-git-receive-pack-advertisement`
|
|
|
|
**Status Codes:**
|
|
- `200 OK` - Success
|
|
- `401 Unauthorized` - Auth required for push
|
|
- `403 Forbidden` - Permission denied
|
|
- `404 Not Found` - Repository not found
|
|
|
|
---
|
|
|
|
### Upload Pack (Clone/Fetch/Pull)
|
|
|
|
**Pattern:** `POST /{namespace}/{name}.git/git-upload-pack`
|
|
|
|
**Purpose:** Download objects from repository (git clone, git fetch, git pull)
|
|
|
|
**Authentication:** Optional (required for private repos)
|
|
|
|
**Request:**
|
|
- `Content-Type`: `application/x-git-upload-pack-request`
|
|
- Body: Git pack negotiation in pkt-line format
|
|
|
|
**Response:**
|
|
- `Content-Type`: `application/x-git-upload-pack-result`
|
|
- Body: Git pack file with requested objects
|
|
|
|
**Process:**
|
|
1. Client sends want/have negotiation
|
|
2. Server generates pack with missing objects
|
|
3. Pack includes LFS pointers for large files (>1MB)
|
|
|
|
**LFS Handling:**
|
|
- Files >1MB converted to LFS pointers automatically
|
|
- Pointer format: Git LFS specification
|
|
- Actual files downloaded via LFS batch API
|
|
|
|
**Status Codes:**
|
|
- `200 OK` - Success
|
|
- `403 Forbidden` - Permission denied
|
|
- `404 Not Found` - Repository not found
|
|
|
|
---
|
|
|
|
### Receive Pack (Push)
|
|
|
|
**Pattern:** `POST /{namespace}/{name}.git/git-receive-pack`
|
|
|
|
**Purpose:** Upload objects to repository (git push)
|
|
|
|
**Authentication:** Required (HTTP Basic Auth)
|
|
|
|
**Request:**
|
|
- `Content-Type`: `application/x-git-receive-pack-request`
|
|
- Body: Git pack file with objects
|
|
|
|
**Response:**
|
|
- `Content-Type`: `application/x-git-receive-pack-result`
|
|
- Body: Status report in pkt-line format
|
|
|
|
**Process:**
|
|
1. Client sends pack with new commits/objects
|
|
2. Server validates and stores objects in LakeFS
|
|
3. Server updates branch references
|
|
4. Server sends status report
|
|
|
|
**Status Codes:**
|
|
- `200 OK` - Success
|
|
- `401 Unauthorized` - Auth required
|
|
- `403 Forbidden` - Permission denied
|
|
- `404 Not Found` - Repository not found
|
|
|
|
---
|
|
|
|
### HEAD Reference
|
|
|
|
**Pattern:** `GET /{namespace}/{name}.git/HEAD`
|
|
|
|
**Purpose:** Get default branch reference
|
|
|
|
**Response:**
|
|
```
|
|
ref: refs/heads/main
|
|
```
|
|
|
|
**Headers:**
|
|
- `Content-Type`: `text/plain`
|
|
|
|
---
|
|
|
|
## SSH Keys Management
|
|
|
|
### List SSH Keys
|
|
|
|
**Pattern:** `GET /api/user/keys`
|
|
|
|
**Authentication:** Required (current user)
|
|
|
|
**Response:**
|
|
```json
|
|
[
|
|
{
|
|
"id": 1,
|
|
"title": "My Laptop",
|
|
"key_type": "ssh-ed25519",
|
|
"fingerprint": "SHA256:abc123def456...",
|
|
"created_at": "2025-01-01T00:00:00Z",
|
|
"last_used": "2025-01-02T12:30:00Z"
|
|
}
|
|
]
|
|
```
|
|
|
|
---
|
|
|
|
### Add SSH Key
|
|
|
|
**Pattern:** `POST /api/user/keys`
|
|
|
|
**Authentication:** Required (current user)
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"title": "My Laptop",
|
|
"key": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5... user@host"
|
|
}
|
|
```
|
|
|
|
**Supported Key Types:**
|
|
- `ssh-ed25519` (recommended)
|
|
- `ssh-rsa` (2048+ bits)
|
|
- `ecdsa-sha2-nistp256`
|
|
- `ecdsa-sha2-nistp384`
|
|
- `ecdsa-sha2-nistp521`
|
|
|
|
**Validation:**
|
|
- Key format must be valid OpenSSH format
|
|
- Title is required (max 255 chars)
|
|
- Duplicate keys rejected (same fingerprint)
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"id": 2,
|
|
"title": "My Laptop",
|
|
"key_type": "ssh-ed25519",
|
|
"fingerprint": "SHA256:abc123...",
|
|
"created_at": "2025-01-15T10:00:00Z",
|
|
"last_used": null
|
|
}
|
|
```
|
|
|
|
**Status Codes:**
|
|
- `200 OK` - Created successfully
|
|
- `400 Bad Request` - Invalid key format
|
|
- `409 Conflict` - Key already exists
|
|
|
|
---
|
|
|
|
### Get SSH Key
|
|
|
|
**Pattern:** `GET /api/user/keys/{key_id}`
|
|
|
|
**Authentication:** Required (must own key)
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"id": 1,
|
|
"title": "My Laptop",
|
|
"key_type": "ssh-ed25519",
|
|
"fingerprint": "SHA256:abc123...",
|
|
"public_key": "ssh-ed25519 AAAAC3...",
|
|
"created_at": "2025-01-01T00:00:00Z",
|
|
"last_used": "2025-01-02T12:30:00Z"
|
|
}
|
|
```
|
|
|
|
**Status Codes:**
|
|
- `200 OK` - Success
|
|
- `403 Forbidden` - Not authorized
|
|
- `404 Not Found` - Key not found
|
|
|
|
---
|
|
|
|
### Delete SSH Key
|
|
|
|
**Pattern:** `DELETE /api/user/keys/{key_id}`
|
|
|
|
**Authentication:** Required (must own key)
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "SSH key deleted successfully"
|
|
}
|
|
```
|
|
|
|
**Status Codes:**
|
|
- `200 OK` - Deleted successfully
|
|
- `403 Forbidden` - Not authorized
|
|
- `404 Not Found` - Key not found
|
|
|
|
---
|
|
|
|
## Git Usage Examples
|
|
|
|
### Clone Repository
|
|
|
|
```bash
|
|
# HTTPS (with token)
|
|
git clone https://token@hub.example.com/username/repo.git
|
|
|
|
# HTTPS (with credential helper)
|
|
git clone https://hub.example.com/username/repo.git
|
|
# Enter username and token when prompted
|
|
|
|
# SSH (requires SSH key setup)
|
|
git clone ssh://git@hub.example.com/username/repo.git
|
|
```
|
|
|
|
### Push Changes
|
|
|
|
```bash
|
|
# Add changes
|
|
git add .
|
|
git commit -m "Update model"
|
|
|
|
# Push to main branch
|
|
git push origin main
|
|
```
|
|
|
|
### Fetch/Pull Updates
|
|
|
|
```bash
|
|
# Fetch updates
|
|
git fetch origin
|
|
|
|
# Pull and merge
|
|
git pull origin main
|
|
```
|
|
|
|
---
|
|
|
|
## LFS Integration
|
|
|
|
Git operations automatically handle LFS files:
|
|
|
|
**On Clone:**
|
|
- Small files (<1MB) downloaded normally
|
|
- Large files (≥1MB) converted to LFS pointers
|
|
- Use `git lfs pull` to download actual LFS files
|
|
|
|
**On Push:**
|
|
- LFS files automatically uploaded via LFS batch API
|
|
- Regular files uploaded via git protocol
|
|
- Server validates and links LFS objects
|
|
|
|
**LFS Commands:**
|
|
```bash
|
|
# Install Git LFS
|
|
git lfs install
|
|
|
|
# Track large file types
|
|
git lfs track "*.safetensors"
|
|
git lfs track "*.bin"
|
|
|
|
# Pull LFS files
|
|
git lfs pull
|
|
|
|
# Push with LFS
|
|
git add large_file.safetensors
|
|
git commit -m "Add model weights"
|
|
git push origin main
|
|
```
|
|
|
|
---
|
|
|
|
## Authentication Methods
|
|
|
|
### HTTPS with Token
|
|
|
|
**URL format:**
|
|
```
|
|
https://token@hub.example.com/namespace/repo.git
|
|
```
|
|
|
|
**Credential Helper:**
|
|
```bash
|
|
# Store credentials
|
|
git config credential.helper store
|
|
|
|
# Or use OS keychain
|
|
git config credential.helper osxkeychain # macOS
|
|
git config credential.helper wincred # Windows
|
|
git config credential.helper libsecret # Linux
|
|
```
|
|
|
|
### SSH with Key
|
|
|
|
**Prerequisites:**
|
|
1. Add SSH public key via API or UI
|
|
2. Configure SSH client
|
|
|
|
**SSH Config (~/.ssh/config):**
|
|
```
|
|
Host hub.example.com
|
|
HostName hub.example.com
|
|
User git
|
|
Port 22
|
|
IdentityFile ~/.ssh/id_ed25519
|
|
```
|
|
|
|
**Clone:**
|
|
```bash
|
|
git clone ssh://git@hub.example.com/username/repo.git
|
|
```
|
|
|
|
---
|
|
|
|
## Error Handling
|
|
|
|
### Common Errors
|
|
|
|
**401 Unauthorized:**
|
|
```
|
|
fatal: Authentication failed for 'https://hub.example.com/repo.git/'
|
|
```
|
|
**Solution:** Check token or SSH key
|
|
|
|
**403 Forbidden:**
|
|
```
|
|
fatal: unable to access 'https://hub.example.com/repo.git/': The requested URL returned error: 403
|
|
```
|
|
**Solution:** Check repository permissions
|
|
|
|
**404 Not Found:**
|
|
```
|
|
fatal: repository 'https://hub.example.com/repo.git/' not found
|
|
```
|
|
**Solution:** Verify repository exists and you have access
|
|
|
|
---
|
|
|
|
## Performance Notes
|
|
|
|
**Clone Speed:**
|
|
- Small repos (<100MB): ~10-30 seconds
|
|
- Large repos (1GB+): Minutes (depends on network)
|
|
- LFS files excluded from initial clone (download separately)
|
|
|
|
**Push Speed:**
|
|
- Incremental pushes: Fast (only new objects)
|
|
- Large files: Use LFS for >1MB files
|
|
- Parallel uploads: LFS batch API supports concurrent uploads
|
|
|
|
**Best Practices:**
|
|
- Use LFS for files >1MB
|
|
- Shallow clone for CI/CD: `git clone --depth 1`
|
|
- Use sparse checkout for large repos
|
|
- Configure `.gitattributes` for LFS tracking
|
|
|
|
---
|
|
|
|
## Next Steps
|
|
|
|
- [Git LFS API](./git-lfs.md) - Detailed LFS protocol
|
|
- [File Upload API](./file-upload.md) - Direct file uploads
|
|
- [Authentication](./authentication.md) - Token management
|