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 merge

Command reference for `libra merge`

Merge one target into the current branch.

Synopsis

libra merge [--ff-only | --no-ff | --squash | --no-commit] [-m <msg>] [--no-edit] [--stat | -n | --no-stat] [--verify-signatures | --no-verify-signatures] [--no-rerere-autoupdate] [--no-gpg-sign] [--dry-run] [--autostash | --no-autostash] <branch>
libra merge --continue
libra merge --abort
libra merge --restart

Description

libra merge <branch> resolves a local branch, commit hash, or remote-tracking ref such as refs/remotes/origin/main.

If the current branch can be fast-forwarded, Libra moves the branch pointer to the target commit and restores the index and working tree. If the branches have diverged, Libra performs a single-head three-way merge using the merge base.

Clean three-way merges create a two-parent merge commit, update HEAD, rebuild the index, restore the working tree, and write a merge reflog entry. Conflicting three-way merges write line-level conflict markers to the working tree (matching Git — only the diverging hunks are enclosed between <<<<<<< HEAD / ======= / >>>>>>>, with shared context left outside; binary or modify/delete paths fall back to whole-file markers), write unmerged index stages, save Libra merge state, and return LBR-CONFLICT-002 with hints for libra merge --continue and libra merge --abort.

Conflict style (merge.conflictStyle)

The marker format follows the Git-compatible merge.conflictStyle config key (config-only — matching Git, merge has no CLI style flag):

libra config merge.conflictStyle diff3
  • merge (default, or unset) — the two-marker style above.
  • diff3 — additionally emits the common-ancestor content between a ||||||| base marker and the ======= separator, so you can see what both sides started from.
  • Any other value — including the unimplemented zdiff3 — is a hard error when a conflict must be rendered (exit 128), never a silent fall-back to the default style.

The config is honored by both libra merge and libra cherry-pick for line-level text conflicts. Binary and modify/delete conflicts keep their two-part whole-file presentation (Git also emits no base block there), and libra rebase currently renders whole-file markers without a base block regardless of this setting.

Libra still does not implement octopus merges, custom strategies, strategy options, or interactive message editing (--edit/launching an editor). Signature verification (--verify-signatures) is supported but limited to the local vault PGP key (no external GPG keyring).

Options

OptionDescription
<branch>Target branch, commit, or remote-tracking ref to merge.
-m, --message <MSG>Override the merge commit message (default Merge <branch> into <head>).
--ff-onlyRefuse to merge unless the current branch can be fast-forwarded.
--no-ffAlways create a two-parent merge commit, even when a fast-forward is possible.
--squashProduce the merged index/working tree but create no commit and do not move HEAD; finish with a plain libra commit.
--no-commitPerform the merge and stage the result but stop before committing; finish with libra merge --continue.
--no-editAccept the auto-generated merge message without launching an editor. Libra never opens an editor for merge, so this is a no-op accepted for Git parity.
--statShow a diffstat of the merge result (the changes between the pre-merge HEAD and the new commit) after the merge completes. Git shows this by default; Libra defaults to no diffstat, so --stat opts in. Last-one-wins toggle with --no-stat/-n. Human output only.
-n, --no-statDo not show a diffstat at the end of the merge (Libra's default). Last-one-wins toggle with --stat.
--no-progressDo not show a progress meter. No-op accepted for Git parity: Libra's merge never renders a progress meter.
--verify-signaturesVerify the PGP signature on the tip commit of the merged branch and abort the merge if it is unsigned or the signature is bad. Like tag -v, only signatures made by this repository's vault PGP key can be validated (no external GPG keyring), so a commit signed elsewhere — or with an SSH signature — is treated as not verifiable.
--no-verify-signaturesDo not verify the merged commit's signature (the default). The inverse of --verify-signatures; the last one wins.
--no-rerere-autoupdateDo not update the rerere index after the merge. No-op accepted for Git parity: Libra has no rerere. (Git's --rerere-autoupdate is not exposed.)
--no-gpg-signDo not GPG-sign the merge commit. No-op accepted for Git parity: Libra's merge never signs. (Git's -S/--gpg-sign is not implemented.)
--continueFinish an in-progress merge after conflicts have been resolved and staged.
--abortRestore the pre-merge HEAD, index, and working tree (re-applies a held autostash).
--autostash / --no-autostashStash local tracked changes (incl. staged) before the merge and re-apply them when it concludes — held (outside stash list) across a conflict until --continue/--abort; a conflicting re-apply is saved to the stash list with a notice, never lost. Config: merge.autostash (boolean; invalid value = hard error). Untracked files are not stashed (Git parity). --json adds autostash: applied|stashed|kept.
--dry-runLibra extension: preview the merge outcome writing nothing — reports fast-forward / already-up-to-date / clean three-way / would-conflict (with the paths). Exits 0 for a clean preview, 1 when the merge would conflict. Mutually exclusive with --continue/--abort/--restart/--squash/--no-commit.
--restartLibra extension (ports Lore's branch merge restart): abort the in-progress conflicted merge — discarding any resolution work, exactly like --abort — then immediately re-run the same merge against the recorded target commit, regenerating fresh conflict markers and state. Takes no branch and no merge options (the original -m/--no-ff/… are not replayed). Requires a conflicted merge: a staged --no-commit merge is refused (finish it with --continue or discard with --abort).
--jsonEmit a structured success envelope.
--machineEmit the same structured envelope as one compact JSON line.
--quietSuppress human success output.

Common Commands

libra merge feature-x
libra merge refs/remotes/origin/main
libra merge --continue
libra merge --abort
libra merge --dry-run feature-x
libra merge --restart
libra merge --json feature-x

Conflict Lifecycle

When a merge conflicts:

  1. Edit files containing conflict markers.
  2. Stage each resolved path with libra add <path>.
  3. Run libra merge --continue to create the two-parent merge commit.

Run libra merge --abort before continuing to restore the branch, index, and working tree to the pre-merge commit. libra status shows the in-progress merge target and the continue/abort commands while merge state exists.

To throw away a botched resolution attempt and start over in one step, run libra merge --restart: it restores the pre-merge state exactly like --abort (any edits to conflicted files are discarded) and immediately re-runs the same merge against the recorded target commit — deterministic even if the branch has moved since — leaving fresh conflict markers and a fresh merge state. The re-run uses default merge options.

Dry Run

libra merge --dry-run <branch> (a Libra extension — Git has no true merge dry-run) reports what the merge would do without writing anything: no HEAD, index, working-tree, reflog, merge-state, or object-store mutation (auto-merged blobs are computed in memory only). Because it is read-only it also works on a dirty working tree — note the preview does not validate cleanliness, so a real merge may still refuse where the preview succeeded.

Outcomes and exit codes:

Preview outcomeHuman outputExit
Fast-forward possibleWould fast-forward0
Already up to dateAlready up to date.0
Clean three-way mergeWould merge cleanly by the 'three-way' strategy.0
Would conflictWould conflict in: <paths>1

The would-conflict exit of 1 is an outcome signal (like merge-file and diff --exit-code), deliberately distinct from the 128 a real conflicting merge exits with — the preview itself succeeded. With --json/--machine the summary carries "dry_run": true and, when conflicting, "would_conflict": true plus conflicted_paths; both keys are absent from every real merge's output (frozen schema).

Human Output

Fast-forward:

Fast-forward

Clean three-way merge:

Merge made by the 'three-way' strategy.

Already up to date:

Already up to date.

After --continue:

Merge completed.

After --abort:

Merge aborted.

Conflict errors are printed through Libra's standard structured error envelope on stderr and include recovery hints.

JSON / Machine Output

Success output keeps the historical files_changed numeric field and adds merge-lifecycle fields only when relevant.

{
  "ok": true,
  "command": "merge",
  "data": {
    "strategy": "three-way",
    "old_commit": "abc1234...",
    "commit": "def5678...",
    "files_changed": 2,
    "up_to_date": false,
    "parents": ["abc1234...", "fedcba9..."]
  }
}

Already-up-to-date merges use strategy: "already-up-to-date", commit: null, files_changed: 0, and up_to_date: true.

--abort sets aborted: true; --continue sets continued: true. Conflict failures return an error envelope on stderr with LBR-CONFLICT-002.

Parameter Comparison: Libra vs Git vs jj

ParameterLibraGitjj
Branch target<branch> (single target)<commit>... (one or more)N/A (use jj new)
Fast-forwardSupportedSupportedN/A
Single-head three-waySupportedSupportedN/A
Continue / abort--continue, --abort--continue, --abortN/A
Octopus mergeNot supportedSupportedN/A
Fast-forward only--ff-only--ff-onlyN/A
Force merge commit--no-ff--no-ffN/A
Squash--squash--squashN/A
No-commit--no-commit--no-commitN/A
Commit message-m <msg>-m <msg>N/A
No editor--no-edit (no-op; never edits)--no-editN/A
Post-merge diffstat--stat (prints it); -n / --no-stat (default: omit)--stat (default) / -n / --no-statN/A
No progress meter--no-progress (no-op; never renders one)--no-progressN/A
Disable signature verification--no-verify-signatures (default; disables --verify-signatures)--no-verify-signaturesN/A
No rerere autoupdate--no-rerere-autoupdate (no-op; no rerere)--no-rerere-autoupdateN/A
No GPG sign--no-gpg-sign (no-op; never signs)--no-gpg-signN/A
Custom strategyNot supported--strategy, -XN/A
Verify signatures--verify-signatures (vault-key PGP only)--verify-signaturesN/A
JSON output--json / --machineNot supportedN/A

Error Handling

ScenarioStableErrorCodeExit
Missing branch / actionLBR-CLI-001129
Target ref cannot be resolvedLBR-CLI-003129
Failed to load merge target/current commit/treeLBR-REPO-002128
Unrelated historiesLBR-REPO-003128
--verify-signatures: tip unsigned, signature invalid, or vault unavailableLBR-REPO-003128
Merge conflictsLBR-CONFLICT-002128
Dirty worktree or staged changesLBR-CONFLICT-002128
Untracked file would be overwrittenLBR-CONFLICT-002128
Merge already in progressLBR-CONFLICT-002128
No merge in progress for --continue / --abortLBR-REPO-003128
Unsupported merge.conflictStyle value (e.g. zdiff3) when rendering a conflictLBR-REPO-003128
Unresolved conflict stages remain for --continueLBR-CONFLICT-002128
Failed to read merge state or indexLBR-IO-001128
Failed to save state, index, tree, commit, HEAD, or worktreeLBR-IO-002128

libra merge-file

Command reference for `libra merge-file`

libra metadata

Command reference for `libra metadata`

On this page

SynopsisDescriptionConflict style (merge.conflictStyle)OptionsCommon CommandsConflict LifecycleDry RunHuman OutputJSON / Machine OutputParameter Comparison: Libra vs Git vs jjError Handling