LibraLibra
LibraLibra
DocsBlogLibra
Getting Started
Architecture
Design
Commands
libra addlibra agentlibra alternateslibra applylibra archivelibra authlibra automationlibra bisectlibra blamelibra branchlibra bundlelibra cachelibra cat-filelibra check-attrlibra check-ignorelibra check-mailmaplibra checkoutlibra cherry-picklibra cleanlibra clonelibra cloudlibra code-controllibra codelibra commit-treelibra commitlibra completionslibra configlibra credentiallibra depslibra describelibra diff-fileslibra diff-indexlibra diff-treelibra difflibra dirtylibra fast-exportlibra fast-importlibra fetchlibra filelibra for-each-reflibra format-patchlibra fscklibra gclibra graphlibra greplibra hash-objectlibra hookslibra hydratelibra index-packlibra initlibra investigatelibra layerlibra lfslibra loglibra logfilelibra loginlibra logoutlibra ls-fileslibra ls-remotelibra ls-treelibra maintenancelibra medialibra merge-baselibra merge-filelibra mergelibra metadatalibra mvlibra noteslibra oplibra openlibra pack-objectslibra packagelibra prunelibra publishlibra pulllibra pushlibra read-treelibra rebaselibra refloglibra remotelibra repacklibra replacelibra rererelibra resetlibra restorelibra rev-listlibra rev-parselibra revertlibra reviewlibra revisionlibra rmlibra sandboxlibra servicelibra shortloglibra show-reflibra showlibra sparse-viewlibra stashlibra statslibra statuslibra switchlibra symbolic-reflibra taglibra update-indexlibra update-reflibra usagelibra verify-packlibra whoamilibra worktreelibra write-tree
API Reference
Policy
Commands

libra fetch

Command reference for `libra fetch`

Download objects and update remote-tracking refs from another repository.

Synopsis

libra fetch [OPTIONS] [<repository> [<refspec>]]

Description

libra fetch contacts a remote repository, negotiates which objects the local store is missing, downloads them as a pack file, indexes the pack, and updates the corresponding remote-tracking refs (e.g. refs/remotes/origin/main). It never modifies the working tree or the current branch -- use libra pull or libra merge for that.

When invoked with no arguments, it fetches from the current branch's configured upstream. When --all is given, every configured remote is fetched in sequence. When a specific <repository> is named, only that remote is contacted. An optional <refspec> narrows the fetch to a single branch.

Fetch supports SSH, HTTPS, local file, and git:// transports. Vault-backed SSH keys are loaded automatically when configured via vault.ssh.<remote>.privkey.

Options

Flag / ArgumentDescriptionExample
<repository>Remote name or URL to fetch from. When omitted, uses the current branch's upstream remote.libra fetch origin
<refspec>Branch name to fetch. Requires <repository>. When omitted, all branches from the remote are fetched.libra fetch origin main
-a, --allFetch from every configured remote. Conflicts with <repository>.libra fetch --all
--depth <N>Limit fetching to the specified number of commits from the tip of each remote branch (shallow fetch). Public stable flag.libra fetch origin --depth 1
--tagsFetch every tag from the remote into the local refs/tags/* (overrides the default auto-follow and remote.<name>.tagOpt).libra fetch origin --tags
--no-tagsFetch no tags at all, not even tags reachable from fetched commits (overrides the default auto-follow).libra fetch origin --no-tags
--no-auto-gcDo not run a repacking/gc pass after fetching. Accepted no-op for Git parity: Libra's fetch never triggers an automatic gc, so there is nothing to disable.libra fetch origin --no-auto-gc
--no-progressDo not show the progress meter (the "Receiving objects" spinner / remote progress) on stderr, matching git fetch --no-progress.libra fetch origin --no-progress
-p, --pruneAfter the fetch, delete remote-tracking refs under refs/remotes/<remote>/* that the remote no longer advertises (reusing remote prune's stale classification). Deletions plus an audit reflog entry run in one transaction. Local branches, tags, refs/remotes/<remote>/HEAD, and other remotes are never touched. With --dry-run, the stale refs are reported but not deleted.libra fetch origin -p
--no-pruneDo not prune remote-tracking refs (the default). --prune/--no-prune form a last-one-wins toggle: when both are given, the last on the command line wins (Git semantics).libra fetch origin --no-prune
--notesAlso import the file-dependency graph (refs/notes/deps, lore.md 3.2) from the remote over a dedicated side-channel. Default OFF (Git never auto-fetches notes). v1 travels notes only from a local Libra source; a network or plain-Git remote emits an honest "not supported yet" warning and imports no graph (deferred, D17). Import union-merges into any local edges and re-validates every endpoint, and is per-note fault-tolerant (a malformed note, or one whose commit is absent locally, is skipped with a warning, never aborting the fetch). Persist the opt-in per remote with remote.<name>.fetchNotesDeps=true.libra fetch origin --notes
-f, --forceAllow non-fast-forward updates and overwrite (clobber) a local tag that points elsewhere. Forced updates are marked + in --porcelain / (forced update) in human output.libra fetch origin --tags --force
--dry-runPreview the remote-tracking ref updates the fetch would produce without downloading any objects or writing refs, reflog, or FETCH_HEAD.libra fetch origin --dry-run
--appendAppend fetched ref records to .libra/FETCH_HEAD instead of overwriting it. (-a is reserved for --all.)libra fetch origin --append
-v, --verboseAnnounce the remote being contacted on stderr; the stdout result contract is unchanged.libra fetch origin -v
--porcelainPrint a machine-readable <flag> <old-oid> <new-oid> <local-ref> line per ref update. Mutually exclusive with --json.libra fetch origin --porcelain
--jsonEmit structured JSON envelope to stdout (global flag).libra --json fetch origin
--machineCompact single-line JSON; suppresses progress (global flag).libra --machine fetch origin
--progress noneSuppress NDJSON progress events on stderr in JSON mode.libra --json fetch origin --progress none
--quietSuppress human-readable output.libra fetch --quiet

Common Commands

libra fetch
libra fetch origin
libra fetch origin main
libra fetch --all
libra fetch origin --depth 1               # shallow fetch
libra fetch origin --tags                  # also fetch all tags into refs/tags/*
libra fetch --all --depth 3                # shallow across all remotes
libra fetch origin --dry-run               # preview ref updates, write nothing
libra fetch origin --porcelain             # machine-readable per-ref lines
libra fetch origin -v                      # announce the remote on stderr
libra fetch origin --append                # accumulate into FETCH_HEAD
libra --json fetch origin
libra --json fetch origin --progress none

Network timeouts

A network fetch (http(s)://, git://, ssh://) is bounded by these timeouts so a dead or black-holed remote cannot hang the command forever:

TimeoutDefaultWhat it bounds
connect30sthe TCP (+ TLS) handshake when opening the connection
idle60sthe longest gap with no bytes arriving during ref advertisement or pack streaming (it resets whenever data arrives, so a slow-but-steady transfer is not cut off)
first-byte30sthe wait from sending the want list to the first response byte (NAK / pack header) — catches a server that accepts the negotiation but never starts streaming, sooner than the idle timeout would. Applied to git://; http(s)/ssh bound the first response through their own read timeouts

Each is resolved in this precedence order:

  1. an environment variable in milliseconds — LIBRA_FETCH_CONNECT_TIMEOUT_MS, LIBRA_FETCH_IDLE_TIMEOUT_MS, LIBRA_FETCH_FIRST_BYTE_TIMEOUT_MS;
  2. a config value in whole seconds — fetch.<remote>.connectTimeout / fetch.<remote>.idleTimeout / fetch.<remote>.firstByteTimeout, then the un-scoped fetch.connectTimeout / fetch.idleTimeout / fetch.firstByteTimeout;
  3. the built-in default above.
# Give a flaky remote longer to connect, for this remote only.
libra config fetch.origin.connectTimeout 90

# One-off override (milliseconds) without touching config.
LIBRA_FETCH_IDLE_TIMEOUT_MS=120000 libra fetch origin

Local (file:// / path) remotes read from disk and are not subject to network timeouts. git:// connections are now bounded by all three timeouts (previously they had none). An unparseable env/config value is ignored rather than applied, so a typo never leaves a fetch with a zero or nonsensical timeout.

FETCH_HEAD

Every successful fetch records the fetched refs in .libra/FETCH_HEAD, one <oid>\tnot-for-merge\tbranch '<name>' of <url> line per ref. Libra never designates a merge target (merge with libra pull), so every line is marked not-for-merge. --append accumulates into the file instead of overwriting it; --dry-run writes nothing.

Human Output

Successful human mode prints a compact summary:

From /path/to/remote.git
 * [new ref]         origin/main
 32 objects fetched

When nothing changed:

From /path/to/remote.git
Already up to date with 'origin'

Structured Output (JSON examples)

  • --json writes one success envelope to stdout
  • --machine writes the same schema as compact single-line JSON
  • stdout is reserved for the final envelope only

Top-Level Schema

  • all: whether --all was used
  • requested_remote: explicit remote name, or null for --all
  • refspec: requested branch/refspec when provided
  • remotes[]: per-remote fetch results

Per-Remote Result Schema

  • remote: logical remote name
  • url: normalized remote URL/path
  • refs_updated[]: updated remote-tracking refs
  • objects_fetched: object count parsed from the received pack
  • bytes_received: byte size of the received pack stream (0 when nothing was transferred)

Refs Updated Schema

  • remote_ref: fully qualified local remote-tracking ref, e.g. refs/remotes/origin/main
  • old_oid: previous object id, or null when the ref is new
  • new_oid: fetched object id

Example (single remote):

{
  "ok": true,
  "command": "fetch",
  "data": {
    "all": false,
    "requested_remote": "origin",
    "refspec": null,
    "remotes": [
      {
        "remote": "origin",
        "url": "[email protected]:user/repo.git",
        "refs_updated": [
          {
            "remote_ref": "refs/remotes/origin/main",
            "old_oid": "abc1234...",
            "new_oid": "def5678..."
          }
        ],
        "objects_fetched": 32,
        "bytes_received": 4096
      }
    ]
  }
}

Example (already up to date):

{
  "ok": true,
  "command": "fetch",
  "data": {
    "all": false,
    "requested_remote": "origin",
    "refspec": null,
    "remotes": [
      {
        "remote": "origin",
        "url": "[email protected]:user/repo.git",
        "refs_updated": [],
        "objects_fetched": 0,
        "bytes_received": 0
      }
    ]
  }
}

Progress

  • In --json mode, progress defaults to NDJSON events on stderr
  • Use --progress none to keep stderr quiet in JSON mode
  • --machine disables progress automatically and keeps stderr clean on success

Design Rationale

Pruning is opt-in, not the default

Git ships fetch.prune = true as a recommended default because stale remote-tracking refs accumulate silently. Libra does not prune by default for two reasons: (1) in agent-driven workflows, stale tracking refs can serve as useful historical anchors for diffing against a previous remote state, and (2) destructive ref cleanup should be a deliberate choice. Pruning is therefore opt-in via --prune/-p (or the standalone libra remote prune <name>). --no-prune is the default; --prune/--no-prune form a last-one-wins toggle, matching Git.

When --prune is given, after the fetch completes Libra removes every refs/remotes/<remote>/* ref the remote no longer advertises, classified by the same rule remote prune uses. The deletions and a non-lossy audit reflog entry (<old> -> 0…0) run in a single transaction, so a mid-prune failure rolls back every deletion. --dry-run reports the stale refs without writing. Documented narrowings versus Git: pruning is full-remote scoped (it cleans every stale tracking ref for the remote, like remote prune, rather than restricting to an explicit refspec), it is skipped entirely when the remote advertises no refs at all (so a transient empty advertisement cannot wipe every tracking ref), and pruned refs never appear in FETCH_HEAD (which records only fetched refs).

Shallow fetch (--depth) is exposed as a stable flag

libra fetch --depth N is a public stable flag (audited C3 in docs/development/commands/clone.md). The internal fetch_repository(..., depth) plumbing has supported shallow fetch for some time; C3 surfaces it on the CLI and binds the contract:

  • --depth N limits fetching to the latest N commits per remote branch.
  • It composes with --all: a shallow fetch across all configured remotes is libra fetch --all --depth N.
  • A full-history fetch followed by fetch --depth N is idempotent.
  • Re-fetching an already-shallow repository at the same depth is also idempotent: Libra persists server-advertised shallow boundaries in .libra/shallow and sends them during later upload-pack negotiation.
  • Sparse checkout (clone --sparse) is not part of this contract — see docs/development/commands/_compatibility.md for why sparse-checkout is intentionally deferred.

Shallow fetch does introduce the usual Git "shallow boundary" caveats (blame, log, merge-base computation may not see commits beyond the boundary). That trade-off is a user-visible knob, not a default — full-history fetch remains the default and the recommended posture for monorepo and AI-agent workflows. Tiered cloud storage (S3/R2 + LRU caching) remains the bandwidth solution for the cases where full history is wanted.

Why JSON progress on stderr?

Structured progress events (object counts, bytes received) are emitted as NDJSON lines on stderr so that agent frameworks can parse real-time progress without interfering with the final result envelope on stdout. This follows the Unix convention of separating status information (stderr) from data output (stdout). The --progress none flag allows callers that do not need progress to suppress it entirely, and --machine mode disables progress by default for maximum script friendliness.

Parameter Comparison: Libra vs Git vs jj

ParameterLibraGitjj
Fetch upstreamlibra fetchgit fetchjj git fetch
Named remotelibra fetch origingit fetch originjj git fetch --remote origin
Single branchlibra fetch origin maingit fetch origin mainjj git fetch --remote origin --branch main
All remoteslibra fetch --allgit fetch --alljj git fetch --all-remotes
Prune stale refslibra fetch -p / libra remote prune <name>git fetch --pruneAutomatic
Shallow fetchlibra fetch --depth Ngit fetch --depth NNot supported
Dry-run previewlibra fetch --dry-rungit fetch --dry-runNot supported
Porcelain outputlibra fetch --porcelaingit fetch --porcelainNo
Append FETCH_HEADlibra fetch --appendgit fetch --appendNo
Verbose diagnosticslibra fetch -vgit fetch -vNo
Tag auto-follow (default)Tags reachable from fetched commits are followed automatically (via include-tag)Same (default)Automatic
Tag fetch controllibra fetch --tags / --no-tags; remote.<name>.tagOptgit fetch --tags / --no-tags; remote.<name>.tagOptAutomatic
Force fetchlibra fetch -f / --force (non-FF + tag clobber)git fetch --forceAutomatic
Atomic / refmapNot supported (deferred)git fetch --atomic / --refmapNo
Structured output--json / --machineNoNo
Progress eventsNDJSON on stderrText on stderrText on stderr

Error Handling

ScenarioStableErrorCodeExitHint
No configured upstream / detached HEADLBR-REPO-003128"checkout a branch or specify a remote"
Remote not foundLBR-CLI-003129"use 'libra remote -v' to see configured remotes"
Remote branch not foundLBR-CLI-003129"verify the remote branch name and try again"
Invalid remote spec (missing repo, malformed URL, unsupported scheme)LBR-CLI-003 or LBR-REPO-001129 / 128Varies by cause
Authentication failure during discoveryLBR-AUTH-002128"check SSH key / HTTP credentials and repository access rights"
Network timeout / transport failureLBR-NET-001128"check network connectivity and retry"
Packet / sideband / checksum / pack protocol failureLBR-NET-002128"the remote did not respond correctly"
Object format mismatchLBR-REPO-003128"remote uses a different hash algorithm"
Failed to create pack directoryLBR-IO-002128"check filesystem permissions"
Failed to write pack/index/refsLBR-IO-002128"check filesystem permissions and disk space"
Local state corruptionLBR-REPO-002128"inspect repository state and object integrity"

libra fast-import

Command reference for `libra fast-import`

libra file

Command reference for `libra file`

On this page

SynopsisDescriptionOptionsCommon CommandsNetwork timeoutsFETCH_HEADHuman OutputStructured Output (JSON examples)Top-Level SchemaPer-Remote Result SchemaRefs Updated SchemaProgressDesign RationalePruning is opt-in, not the defaultShallow fetch (--depth) is exposed as a stable flagWhy JSON progress on stderr?Parameter Comparison: Libra vs Git vs jjError Handling