10 KiB
title, description, icon
| title | description | icon |
|---|---|---|
| Branches & Tags API | Branch/tag management, merge, revert, reset operations | i-carbon-branch |
Branches & Tags API
Manage branches, tags, and advanced Git operations (merge, revert, reset).
Branches
Create Branch
Pattern: POST /api/{repo_type}s/{namespace}/{name}/branch
Authentication: Required (delete permission)
Request Body:
{
"branch": "feature-branch",
"revision": "main"
}
Fields:
branch: New branch name (required)revision: Source revision (branch/commit, default: "main")
Response:
{
"success": true,
"message": "Branch 'feature-branch' created"
}
Status Codes:
200 OK- Branch created404 Not Found- Repository or source revision not found409 Conflict- Branch already exists
Delete Branch
Pattern: DELETE /api/{repo_type}s/{namespace}/{name}/branch/{branch}
Authentication: Required (delete permission)
Protection: Cannot delete "main" branch
Response:
{
"success": true,
"message": "Branch 'feature-branch' deleted"
}
Status Codes:
200 OK- Branch deleted400 Bad Request- Attempting to delete main branch404 Not Found- Repository or branch not found
Merge Branches
Pattern: POST /api/{repo_type}s/{namespace}/{name}/merge/{source_ref}/into/{destination_branch}
Authentication: Required (write permission)
Request Body:
{
"message": "Merge feature into main",
"metadata": {
"author": "alice"
},
"strategy": "dest-wins",
"force": false,
"allow_empty": false,
"squash_merge": false
}
Fields (all optional):
message: Commit messagemetadata: Additional metadatastrategy: Conflict resolution"dest-wins": Destination wins on conflict"source-wins": Source wins on conflictnull: Fail on conflict (default)
force: Force merge even with conflictsallow_empty: Allow merge with no changessquash_merge: Squash all commits into one
Response:
{
"success": true,
"message": "Successfully merged feature into main",
"result": {
"reference": "commit_hash",
"summary": {
"added": 5,
"removed": 2,
"changed": 3
}
}
}
Status Codes:
200 OK- Merged successfully409 Conflict- Merge conflict (use strategy to resolve)500 Internal Server Error- Merge failed
Auto-tracking:
- LFS objects tracked automatically
- Commit recorded in database
- User attribution preserved
Revert Commit
Pattern: POST /api/{repo_type}s/{namespace}/{name}/branch/{branch}/revert
Authentication: Required (write permission)
Purpose: Create new commit that undoes changes from a specific commit
Request Body:
{
"ref": "commit_id_to_revert",
"parent_number": 1,
"message": "Revert: broken feature",
"metadata": {
"reason": "broke production"
},
"force": false,
"allow_empty": false
}
Fields:
ref: Commit ID or ref to revert (required)parent_number: For merge commits (default: 1)message: Commit message (optional)metadata: Additional metadata (optional)force: Force revert even with conflictsallow_empty: Allow empty revert
Response:
{
"success": true,
"message": "Successfully reverted commit abc123de on branch 'main'",
"new_commit_id": "new_commit_hash"
}
Important Notes:
- Creates NEW commit (doesn't delete history)
- LFS files automatically handled (no recoverability check needed)
- If conflicts: returns 409 error
Status Codes:
200 OK- Reverted successfully404 Not Found- Commit not found409 Conflict- Revert caused conflicts
Reset Branch
Pattern: POST /api/{repo_type}s/{namespace}/{name}/branch/{branch}/reset
Authentication: Required (write permission)
Purpose: Reset branch to a specific commit (like git reset --hard)
Request Body:
{
"ref": "commit_id_to_reset_to",
"message": "Reset to stable version",
"force": false
}
Fields:
ref: Commit ID or ref to reset to (required)message: Commit message (optional)force: Skip LFS recoverability check
Safety Checks:
- Main branch requires
force: true - LFS file availability checked (unless
force: true) - Creates new commit (preserves history)
Response:
{
"success": true,
"message": "Successfully reset branch 'main' to commit abc123de (new commit created)",
"commit_id": "new_commit_hash"
}
LFS Recoverability Check:
- Validates all LFS files from target commit still exist
- Checks all commits between target and HEAD
- If files garbage-collected: returns 400 error
Error if LFS unavailable:
{
"error": "Cannot reset to commit abc123: 5 LFS file(s) across 3 commit(s) have been garbage collected",
"missing_files": ["model.safetensors", "data.bin"],
"affected_commits": ["commit1", "commit2", "commit3"],
"recoverable": false
}
Use force: true to bypass check (may break LFS refs)
Status Codes:
200 OK- Reset successful400 Bad Request- LFS files not recoverable or main branch without force404 Not Found- Commit not found
Implementation Details:
- Uses diff-based approach (not destructive)
- Restores files from target commit
- Syncs File table after reset
- Records reset commit in database
Tags
Create Tag
Pattern: POST /api/{repo_type}s/{namespace}/{name}/tag
Authentication: Required (delete permission)
Request Body:
{
"tag": "v1.0.0",
"revision": "main",
"message": "Release version 1.0"
}
Fields:
tag: Tag name (required)revision: Source revision (default: "main")message: Tag message (optional)
Response:
{
"success": true,
"message": "Tag 'v1.0.0' created"
}
Status Codes:
200 OK- Tag created404 Not Found- Repository or revision not found500 Internal Server Error- Failed to create tag
Delete Tag
Pattern: DELETE /api/{repo_type}s/{namespace}/{name}/tag/{tag}
Authentication: Required (delete permission)
Response:
{
"success": true,
"message": "Tag 'v1.0.0' deleted"
}
Status Codes:
200 OK- Tag deleted404 Not Found- Repository or tag not found500 Internal Server Error- Failed to delete tag
Usage Examples
Merge Feature Branch
import requests
API_BASE = "http://localhost:28080/api"
TOKEN = "your_token"
HEADERS = {"Authorization": f"Bearer {TOKEN}"}
# Merge feature into main
response = requests.post(
f"{API_BASE}/models/username/repo/merge/feature-branch/into/main",
json={
"message": "Merge feature: Add new model",
"strategy": "dest-wins" # Main wins on conflicts
},
headers=HEADERS
)
result = response.json()
print(f"Merged: {result['message']}")
print(f"Commit: {result['result']['reference']}")
Revert Bad Commit
# Find the bad commit
commits_resp = requests.get(
f"{API_BASE}/models/username/repo/commits/main?limit=10",
headers=HEADERS
)
commits = commits_resp.json()["commits"]
bad_commit = commits[0]["id"] # Latest commit
# Revert it
revert_resp = requests.post(
f"{API_BASE}/models/username/repo/branch/main/revert",
json={
"ref": bad_commit,
"message": "Revert: broken model weights"
},
headers=HEADERS
)
result = revert_resp.json()
print(f"Reverted: {result['new_commit_id']}")
Reset to Previous Version
# Reset to 3 commits ago
commits_resp = requests.get(
f"{API_BASE}/models/username/repo/commits/main?limit=5",
headers=HEADERS
)
commits = commits_resp.json()["commits"]
target_commit = commits[3]["id"] # 3 commits back
# Reset (with LFS check)
reset_resp = requests.post(
f"{API_BASE}/models/username/repo/branch/main/reset",
json={
"ref": target_commit,
"message": "Reset to stable version",
"force": False # Check LFS availability
},
headers=HEADERS
)
if reset_resp.status_code == 400:
# LFS files not available
error = reset_resp.json()
print(f"Cannot reset: {error['error']}")
print(f"Missing files: {error['missing_files']}")
# Force reset anyway (may break)
reset_resp = requests.post(
f"{API_BASE}/models/username/repo/branch/main/reset",
json={"ref": target_commit, "force": True},
headers=HEADERS
)
result = reset_resp.json()
print(f"Reset to: {result['commit_id']}")
Create Release Tag
# Tag current main branch
tag_resp = requests.post(
f"{API_BASE}/models/username/repo/tag",
json={
"tag": "v1.0.0",
"revision": "main",
"message": "Release version 1.0 - Production ready"
},
headers=HEADERS
)
result = tag_resp.json()
print(result["message"])
# Download specific version
file_url = f"{API_BASE}/models/username/repo/resolve/v1.0.0/model.safetensors"
Git Command Equivalents
Branches
# Create branch
POST /branch {"branch": "feature", "revision": "main"}
# git checkout -b feature main
# Delete branch
DELETE /branch/feature
# git branch -d feature
# Merge
POST /merge/feature/into/main {"strategy": "dest-wins"}
# git checkout main && git merge feature -X theirs
Tags
# Create tag
POST /tag {"tag": "v1.0", "revision": "main"}
# git tag v1.0 main
# Delete tag
DELETE /tag/v1.0
# git tag -d v1.0
Advanced Operations
# Revert
POST /branch/main/revert {"ref": "abc123"}
# git revert abc123
# Reset
POST /branch/main/reset {"ref": "abc123"}
# git reset --hard abc123 (but creates new commit)
Best Practices
Branching Strategy:
- Use
mainfor production - Create feature branches for development
- Merge with
dest-winsto protect main - Tag releases for versioning
LFS Considerations:
- Reset checks LFS availability (prevent broken refs)
- Use
force: trueonly if you understand the risk - Keep
lfs_keep_versionshigh enough for your workflow - Monitor storage after resets/reverts
Safety:
- Always use
force: falsefirst (see errors) - Test merges on feature branches first
- Tag before risky operations (easy rollback)
- Document reset/revert reasons in commit message
Next Steps
- Commits API - View commit history
- File Upload API - Commit files
- Repositories API - Repo management