Skip to main content

Overview

The upload-pack endpoint implements the Git Smart HTTP protocol for fetch operations. This endpoint allows you to clone and pull from repositories through gitGost, which proxies requests directly to GitHub.
Upload-pack operations are read-only and do not modify repository state. They’re used for git clone, git fetch, and git pull operations.

Endpoints

Discovery: Get References

Returns available references (branches, tags) and server capabilities from GitHub.
string
required
GitHub repository owner (user or organization)
string
required
Repository name
string
required
Must be git-upload-pack

Request Headers

string
gitGost sends git/2.0 when proxying to GitHub

Response

string
application/x-git-upload-pack-advertisement
string
None - No authentication required
The response is proxied directly from GitHub and contains: Example Response (pkt-line format):
Implementation: internal/http/handlers.go:409-435 Flow:

Data Transfer: Fetch Objects

Receives a request specifying desired commits (wants) and existing commits (haves), returns a packfile containing the requested objects.
string
required
GitHub repository owner
string
required
Repository name

Request Headers

string
required
application/x-git-upload-pack-request
string
application/x-git-upload-pack-result
string
gitGost sends git/2.0 when proxying

Request Body

The request body uses pkt-line format to specify: Example Request (decoded):

Response

string
application/x-git-upload-pack-result
The response is a packfile containing the requested objects, proxied directly from GitHub. Response Format:
  • Signature: PACK (4 bytes)
  • Version: 2 or 3 (4 bytes, network byte order)
  • Object Count: Number of objects (4 bytes)
  • Objects: Compressed object data
  • Checksum: SHA-1 of the preceding data (20 bytes)
Implementation: internal/http/handlers.go:437-476

Size Limits

To prevent abuse, gitGost enforces a size limit on upload-pack requests:
Source: internal/http/handlers.go:441-442 If exceeded, the server returns:
HTTP Status: 413 Request Entity Too Large

Proxy Architecture

gitGost acts as a transparent proxy for fetch operations:

Why Proxy?

Fetch operations only read data - they don’t expose user identity. There’s no commit metadata to strip.
Direct proxying is faster than re-serving packfiles. GitHub’s CDN delivers optimal performance.
Ensures 100% Git protocol compatibility since GitHub is the authoritative source.
Users always get the exact same data whether they fetch via gitGost or directly from GitHub.

Use Cases

Clone a Repository

What happens:
  1. Git sends GET /info/refs?service=git-upload-pack to discover refs
  2. Git sends POST /git-upload-pack with wants (all branch/tag tips)
  3. gitGost proxies both requests to GitHub
  4. Git receives packfile and reconstructs repository

Fetch Updates

What happens:
  1. Git sends wants (remote branch tips) and haves (local commits)
  2. gitGost proxies request to GitHub
  3. GitHub calculates minimal packfile (only new commits)
  4. Git receives and integrates new commits

Pull Changes

What happens:
  1. Git performs a fetch (as above)
  2. Git merges fetched changes into current branch

Shallow Clone

Shallow clones are fully supported - gitGost proxies the deepen capability to GitHub.

Capabilities

GitHub (via gitGost) advertises these upload-pack capabilities:
capability
Server can acknowledge multiple common commits during negotiation
capability
Enhanced version with detailed negotiation feedback
capability
Server can send thin packs (packs with delta references to objects not in the pack)
capability
Multiplexed communication (progress + data)
capability
Enhanced side-band with 64KB chunks
capability
Pack can use offset deltas
capability
Server supports shallow clones
capability
Client can request commits since a date
capability
Client can request commits not reachable from refs
capability
Client doesn’t need to send ‘done’ in some scenarios
These are determined by GitHub, not gitGost.

Error Handling

Common Errors

Cause: GitHub is unreachable or returned an errorResolution:Code: internal/http/handlers.go:422-425 (discovery), internal/http/handlers.go:464-467 (data transfer)
Cause: Request exceeds 50 MB limitResolution: This should rarely happen in practice. If it does, the repository may have unusual characteristics. Clone directly from GitHub instead.Code: internal/http/handlers.go:445-447
Cause: Malformed request or connection errorResolution: Check network connection, update Git clientCode: internal/http/handlers.go:448-451
Cause: Repository path contains invalid charactersResolution: Ensure owner and repo names only contain alphanumeric characters, hyphens, underscores, and dotsCode: internal/http/router.go:78-92 (validation middleware)

Comparison: Fetch vs Push

Implementation Details

Discovery Handler

Source: internal/http/handlers.go:409-435

Data Transfer Handler

Source: internal/http/handlers.go:437-476

HTTP Client Configuration

Source: internal/http/handlers.go:31
The 30-second timeout is sufficient for most operations. Large repositories may occasionally time out - in such cases, clone directly from GitHub.

Examples

Clone via gitGost

Add as Remote

Shallow Clone for CI

When to Use gitGost for Fetching

Consistent Workflow

Use the same remote for both fetch and push operations

Testing

Test the full gitGost integration including fetch operations

Unified Interface

Build tools that interact with repositories exclusively through gitGost

Monitoring

Track all Git operations through a single endpoint
For most use cases, fetching directly from GitHub is simpler and may be faster. Use gitGost for fetching primarily when you need a unified interface or are testing the service.

Git Smart HTTP

Learn about the protocol gitGost implements

Receive-Pack

Push operations (git push)

Quickstart

Get started with gitGost in 2 minutes

Architecture

System architecture overview