libra pull

Command reference for `libra pull`

Fetch objects from a remote and integrate the fetched branch into the current branch.

Synopsis

libra pull [--ff-only] [--ff] [--no-ff] [--squash] [--no-commit] [--commit] [--autostash] [--no-progress] [--rebase] [--no-rebase] [--depth <n>] [<repository> [<refspec>]]

Description

libra pull combines fetch and the same merge engine used by libra merge. It downloads new objects, updates remote-tracking refs, and then integrates the selected upstream into the current branch.

With --rebase (-r), the integration step instead replays local-only commits on top of the fetched upstream tip. This is equivalent to libra fetch followed by libra rebase <upstream>.

With --ff-only, pull fetches the upstream but refuses to create a merge commit when local and remote histories have diverged. Fast-forward and already-up-to-date pulls still succeed. --ff-only conflicts with --rebase, --ff, and --no-ff.

With --no-ff, pull always records a real merge commit even when the upstream could be fast-forwarded, mirroring git pull --no-ff. --ff explicitly allows the default fast-forward behaviour. --ff, --no-ff, and --ff-only are mutually exclusive and conflict with --rebase.

With --depth <n>, the fetch phase is limited to a shallow history of n commits per tip before integration, mirroring git pull --depth. --depth is fetch-only and conflicts with --rebase.

When invoked with no arguments, the command reads the current branch tracking configuration (branch.<name>.remote and branch.<name>.merge). When <repository> is given alone, the current branch name is used as the remote branch. When both <repository> and <refspec> are given, the specified remote branch is fetched and merged.

Pull supports already-up-to-date, fast-forward, and three-way merge results, including recursive virtual ancestors for multiple merge bases. The merge phase inherits merge's unresolved-index guard. Without merge state, unresolved index stages return LBR-CONFLICT-002 with phase: "merge" and plain-commit guidance—even when the fetched target is already up to date. Fetch may already have downloaded objects or advanced remote-tracking refs, but integration preserves HEAD, the index, and working tree.

For a normal merge conflict, pull leaves merge state: resolve with libra add <path> and libra merge --continue, or abort it with libra merge --abort. A squash conflict leaves no merge state and keeps HEAD unchanged; resolve and stage the paths, then use a plain libra commit to create a single-parent commit.

The merge phase inherits directory-rename inference and merge.directoryRenames=true|false|conflict. The default conflict suggests and stages a relocated path as unresolved, true relocates automatically, and false leaves additions below the old directory. A tied destination stops the merge with affected additions at stage 0. Unknown values fail closed in the merge phase with LBR-REPO-003; fetch may already have updated remote-tracking refs before that phase-local refusal.

The merge path also inherits merge.renormalize=true|false. When enabled, the shared three-way engine canonicalizes text / eol-attributed base, local, and remote inputs before content merge, then preserves local (ours-side) line endings. Pull exposes no -X override; use repository configuration. An invalid value fails with LBR-REPO-003 only when integration reaches a real three-way merge. Fetch may already have updated objects and remote-tracking refs; fast-forward and already-up-to-date integration do not consume the setting. Arbitrary clean/smudge filters remain unsupported.

With --squash, pull fetches and computes the merge but stages the merged tree without creating a commit, moving HEAD, or recording merge state—even when the merge conflicts. With --no-commit, pull performs the merge and stages the result but stops before committing, recording merge state so the two-parent commit can be finalized with libra merge --continue. --squash and --no-commit conflict with each other and with --rebase. --commit forces a merge commit (the default merge behavior) and is last-one-wins with --no-commit (the final flag on the command line decides); it conflicts with --squash and --rebase, matching git pull --commit.

With --autostash, pull stashes tracked changes before integration. The rebase path restores them when the operation returns. A normal merge conflict holds them until merge --continue/--abort; a squash conflict stores them directly in stash list without applying them so the unresolved index remains intact. After resolving and committing a squash, restore them with libra stash pop. Untracked and ignored files remain in place.

Options

Flag / Argument Description Example
<repository> Remote name to pull from. When omitted, uses the current branch's configured upstream. libra pull origin
<refspec> Branch name on the remote. Requires <repository>. When omitted, uses the current branch name. libra pull origin main
--ff-only Refuse to create a merge commit; allows only fast-forward or already-up-to-date integration. Unresolved index stages still refuse the merge phase. Conflicts with --rebase, --ff, --no-ff. libra pull --ff-only
--ff Explicitly allow a fast-forward merge (the default). Conflicts with --no-ff, --ff-only, --rebase. libra pull --ff
--no-ff Always create a merge commit even when a fast-forward is possible. Conflicts with --ff, --ff-only, --rebase. libra pull --no-ff
--squash Stage the merged tree without committing, moving HEAD, or recording merge state, including on conflict. Resolve and stage conflicts, then use a plain single-parent libra commit. libra pull --squash
--no-commit Merge and stage but stop before committing, recording merge state to finalize with libra merge --continue. Conflicts with --squash, --rebase. libra pull --no-commit
--commit Force a merge commit (the default); last-one-wins with --no-commit. Conflicts with --squash, --rebase. libra pull --commit
--autostash Stash tracked changes before integrating. Normal merge conflicts hold them for merge control; squash conflicts save them in stash list for a later stash pop. libra pull --autostash
--no-progress Suppress the fetch progress meter (the "Receiving objects" spinner), matching git pull --no-progress. libra pull --no-progress
--notes Forward to the fetch: also import the file-dependency graph (refs/notes/deps, lore.md 3.2) from a local Libra upstream. Default OFF (Git parity); a network/plain-Git upstream warns and imports nothing (deferred, D17). See libra fetch --notes. libra pull --notes
--depth <n> Limit the fetch phase to a shallow history of n commits per tip. Conflicts with --rebase. libra pull --depth 1
-r, --rebase After fetching, rebase the current branch onto the upstream tip instead of merging. libra pull --rebase
--no-rebase Merge instead of rebasing (the default), countermanding an earlier --rebase/-r (last one wins). Pull merges by default, so on its own this is a no-op. libra pull --no-rebase
--json Emit structured JSON envelope to stdout (global flag). libra pull --json
--machine Compact single-line JSON; suppresses progress (global flag). libra pull --machine
--quiet Suppress all progress and merge summary output. libra pull --quiet

Examples

libra pull
libra pull origin main
libra pull --ff-only
libra pull --no-ff
libra pull --depth 1
libra pull --rebase origin main

Human Output

Default human mode writes fetch progress to stderr and the pull summary to stdout.

Fast-forward:

From git@github.com:user/repo.git
   abc1234..def5678  origin/main
Updating abc1234..def5678
Fast-forward
 3 files changed

Clean three-way merge:

From git@github.com:user/repo.git
   abc1234..def5678  origin/main
Updating abc1234..def5678
Merge made by the 'three-way' strategy.
 2 files changed

Already up to date:

From git@github.com:user/repo.git
Already up to date.

No tracking information:

There is no tracking information for the current branch.
Please specify which branch you want to merge with.
See git-pull(1) for details.

    libra pull <remote> <branch>

If you wish to set tracking information for this branch you can do so with:

    libra branch --set-upstream-to=origin/<branch> main

Rebase:

From git@github.com:user/repo.git
   abc1234..def5678  origin/main
Successfully rebased 2 commits onto 'origin/main' (1111111..2222222).

--quiet suppresses all progress and merge summary output.

Structured Output

--json writes one success envelope to stdout. --machine writes the same schema as one compact JSON line. Success leaves stderr clean.

{
  "ok": true,
  "command": "pull",
  "data": {
    "branch": "main",
    "upstream": "origin/main",
    "fetch": {
      "remote": "origin",
      "url": "git@github.com:user/repo.git",
      "refs_updated": [
        {
          "remote_ref": "refs/remotes/origin/main",
          "old_oid": "abc1234...",
          "new_oid": "def5678..."
        }
      ],
      "objects_fetched": 12,
      "bytes_received": 2048
    },
    "merge": {
      "strategy": "three-way",
      "old_commit": "abc1234...",
      "commit": "def5678...",
      "files_changed": 2,
      "up_to_date": false,
      "parents": ["abc1234...", "fedcba9..."]
    }
  }
}

Rebase output omits merge and includes rebase:

{
  "ok": true,
  "command": "pull",
  "data": {
    "branch": "main",
    "upstream": "origin/main",
    "fetch": {
      "remote": "origin",
      "url": "git@github.com:user/repo.git",
      "refs_updated": [],
      "objects_fetched": 0,
      "bytes_received": 0
    },
    "rebase": {
      "status": "completed",
      "old_commit": "1111111...",
      "commit": "2222222...",
      "replay_count": 2,
      "up_to_date": false
    }
  }
}

Schema Notes

  • branch is the current local branch being updated.
  • upstream is the remote tracking branch name, such as "origin/main".
  • fetch.refs_updated lists remote refs that changed during fetch.
  • Exactly one of merge or rebase is present, depending on whether --rebase was passed.
  • merge.old_commit is the pre-merge HEAD; it is null on the first pull into an empty local branch.
  • merge.strategy is "fast-forward", "three-way", or "already-up-to-date".
  • merge.commit is the new HEAD commit after merge; it is null when up to date.
  • merge.parents appears for successful three-way merge commits.
  • merge.files_changed is the number of paths changed by the merge result.
  • rebase.status is "completed", "fast-forwarded", "already-up-to-date", or "no-commits".
  • rebase.replay_count is the number of local commits replayed onto the upstream tip.
  • rebase.up_to_date is true when the rebase did not move HEAD.

Parameter Comparison: Libra vs Git vs jj

Parameter Libra Git jj
Basic pull libra pull git pull N/A (jj uses jj git fetch + working copy)
Pull from specific remote libra pull origin main git pull origin main N/A
Fast-forward integration Supported Supported N/A
Fast-forward-only pull libra pull --ff-only git pull --ff-only N/A
Three-way integration Supported through merge engine Supported N/A
Rebase on pull libra pull --rebase git pull --rebase N/A
Force merge commit libra pull --no-ff git pull --no-ff N/A
Shallow pull libra pull --depth 1 git pull --depth 1 N/A
Squash libra pull --squash git pull --squash N/A
No-commit libra pull --no-commit (finalize with libra merge --continue) git pull --no-commit N/A
Force-commit override libra pull --commit (last-one-wins with --no-commit) git pull --commit N/A
Autostash libra pull --autostash git pull --autostash N/A
Suppress progress libra pull --no-progress git pull --no-progress N/A
Structured output --json / --machine No No
Phase diagnostics phase detail in error JSON No No

Error Handling

Every PullError variant maps to an explicit StableErrorCode. Fetch, merge, and rebase sub-errors are forwarded with a phase detail for diagnostics.

Scenario Error Code Exit Hint
HEAD is detached LBR-REPO-003 128 "checkout a branch before pulling"
No tracking info for branch LBR-REPO-003 128 Git-style advisory block with libra pull <remote> <branch> and libra branch --set-upstream-to=...
Remote not found LBR-CLI-003 129 "use 'libra remote -v' to see configured remotes"
Fetch: network unreachable / timeout LBR-NET-001 128 "check network connectivity and retry"
Fetch: authentication failed LBR-AUTH-001 128 "check SSH key or HTTP credentials"
Fetch: protocol error LBR-NET-002 128 "the remote did not respond correctly"
Merge: conflicts, dirty worktree, or untracked overwrite LBR-CONFLICT-002 128 "resolve conflicts, then run 'libra merge --continue'"
Merge: non-fast-forward rejected by --ff-only LBR-CONFLICT-002 128 "run 'libra pull' without --ff-only to allow a merge commit"
Rebase: conflict during replay LBR-CONFLICT-001 128 "resolve conflicts, stage them, then run 'libra rebase --continue'"
Rebase: dirty worktree LBR-REPO-003 128 "commit or stash your changes before rebasing"
Merge: invalid target LBR-CLI-003 129 "verify the upstream ref and try again"
Merge: unrelated histories or invalid merge state LBR-REPO-003 128 "inspect branch history and merge state"
Merge: repository corruption LBR-REPO-002 128 "inspect repository state and object integrity"
Merge: read failure LBR-IO-001 128 "check repository metadata and permissions"
Merge: write failure LBR-IO-002 128 "check filesystem permissions and retry"

Phase Detail

When a sub-operation fails, the error JSON includes a phase key in the details object ("fetch", "merge", or "rebase") so agents can distinguish which stage failed.