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 commit

Command reference for `libra commit`

Create a new commit from staged changes.

Alias: ci

Synopsis

libra commit [OPTIONS] -m <MESSAGE>
libra commit [OPTIONS] -F <FILE>
libra commit [OPTIONS] -C <COMMIT>
libra commit [OPTIONS] -c <COMMIT>
libra commit [OPTIONS] -t <FILE>
libra commit [OPTIONS] --fixup <COMMIT>
libra commit [OPTIONS] --squash <COMMIT>
libra commit --amend [--no-edit]

Description

libra commit creates a new commit from staged changes, builds tree and commit objects, validates messages (including optional conventional commit format and GPG signing via vault), and updates HEAD and refs.

The command reads the index to determine which files are staged, constructs a tree object hierarchy matching the staged content, creates a commit object with the provided message and author/committer metadata, and advances the current branch ref. When vault signing is enabled, the commit is automatically GPG-signed. Pre-commit and commit-msg hooks are executed unless bypassed with --no-verify.

Options

-m, --message <MESSAGE>

Use the given message as the commit message. When omitted (and no -F/-C/--no-edit source is given), the editor is opened to compose the message.

libra commit -m "Add new feature"

-e, --edit

Open the editor to edit the final message even when -m/-F/-C is given (the supplied message is the initial buffer). Conflicts with --no-edit.

libra commit -e -m "Draft message"

-t, --template <FILE>

Use the contents of FILE as the initial commit message. With the editor open (the default when no other message source is given), FILE seeds the editor buffer; with --no-edit it is used directly. When the -t flag is unset, the commit.template config (a file path, with a leading ~/ expanded to $HOME) is consulted. The template is ignored when a message source (-m/-F/-C/-c/--fixup/--squash) is given — that source wins and the template file is not even read. As in Git, if the editor leaves the template unchanged the commit is aborted ("you did not edit the message"); --no-edit bypasses that check.

libra commit -t .libra/commit-template.txt

-v, --verbose

Show the staged diff in the editor template (below a scissors line, stripped on save) or, when no editor is opened, on stderr. The diff never enters the commit message.

Setting the commit.verbose config to true makes -v the default (an explicit -v on the command line still forces it on). The value is a Git bool-or-int, so commit.verbose=2 is accepted and enables verbose — but Libra's -v is on/off only: there is no -vv verbosity level (no unstaged-diff rendering) and no --no-verbose to force it off for a single commit.

libra commit -v
libra config commit.verbose true   # make -v the default

--no-edit

Reuse the existing message (the --amend parent's, or the one from -m/-F) without opening the editor. Conflicts with --edit.

libra commit --amend --no-edit
libra commit --no-edit -m "msg"

-F, --file <FILE>

Read the commit message from the given file. Mutually exclusive with -m when --no-edit is not in use.

libra commit -F message.txt

--amend

Replace the tip of the current branch by creating a new commit. The new commit has the same parent(s) as the replaced commit. Cannot amend merge commits (commits with multiple parents).

libra commit --amend
libra commit --amend -m "Updated message"

--no-edit

When used with --amend, reuse the message from the original commit without prompting for changes. Conflicts with -m and -F.

libra commit --amend --no-edit

--conventional

Validate the commit message against the Conventional Commits specification (https://www.conventionalcommits.org). The message must match the pattern <type>[optional scope]: <description>. Fails with an error if validation fails.

libra commit -m "feat: add login" --conventional
libra commit -m "fix(auth): handle expired tokens" --conventional

-a, --all

Automatically stage tracked files that have been modified or deleted before committing. Equivalent to running libra add -u before libra commit. Does not add new untracked files.

libra commit -a -m "Fix typo"

-s, --signoff

Add a Signed-off-by trailer at the end of the commit message, using the committer's identity.

libra commit -s -m "Add feature"

--allow-empty

Allow creating a commit with no changes (empty diff from parent). Useful for triggering CI or marking milestones.

libra commit --allow-empty -m "Trigger CI"

--disable-pre

Skip the pre-commit hook only. The commit-msg hook still runs.

libra commit --disable-pre -m "Quick fix"

--no-verify

Skip all pre-commit and commit-msg hooks/validations. Aligns with Git's --no-verify behavior.

libra commit --no-verify -m "WIP: work in progress"

--author <AUTHOR>

Override the commit author. Must use the standard A U Thor <[email protected]> format.

libra commit --author "Jane Doe <[email protected]>" -m "Patch"

--cleanup <MODE>

Clean up the commit message before committing. Accepted values: strip (default, removes commentary lines and trims whitespace), whitespace (only trims whitespace), verbatim (no cleanup), scissors (whitespace cleanup plus truncation at the scissors line — the truncation only applies when the message is edited; on a non-editor -m/-F commit it behaves like whitespace, with no truncation), default (strip when the message is edited, otherwise whitespace).

When --cleanup is not given, the commit.cleanup config value is used as the default (config cascade: local repo, then global); the CLI flag always takes precedence.

libra commit --cleanup=strip -m "feat: add login"
libra config commit.cleanup whitespace   # default cleanup when --cleanup is omitted

--dry-run

Do not actually create the commit. Show the commit summary that would be produced.

libra commit --dry-run -m "Draft commit"

--porcelain

Print the working-tree status in machine-readable porcelain v1 format (the same as libra status --porcelain: staged changes in column 1, unstaged in column 2, untracked as ??, untracked directories collapsed) instead of the human commit summary, mirroring git commit --porcelain. Like Git, --porcelain implies --dry-run: it prints the would-be-committed state and does not create the commit (and leaves the index untouched, even with -a, which is auto-staged only for the preview). Inert under --json (the JSON envelope is emitted instead).

libra commit --porcelain

--status / --no-status

--status seeds the working-tree status, as #-commented lines, into the commit-message editor template (Git shows this by default; Libra defaults to omitting it, so --status opts in). Because the lines are comments, the message cleanup strips them — they are informational only and never enter the final commit message. This has no effect when no editor is opened (e.g. with -m). The status is also omitted under cleanup modes that keep comment lines (--cleanup=verbatim, --cleanup=whitespace, and --cleanup=scissors — explicit scissors keeps # lines above the marker), so it can never leak into the message; it is seeded only when an editor opens and the effective cleanup strips comments (strip/default). -v only truncates the appended diff — it does not force a strip — so the status stays omitted under those modes even with -v. --no-status (the default) omits the status section. The two are a last-one-wins toggle.

libra commit --status          # opens the editor with the status commented in
libra commit --no-status -m "message"

--no-gpg-sign

Force an unsigned commit: skip Libra's vault GPG signing for this commit, matching git commit --no-gpg-sign. Vault signing runs when vault.signing=true (the libra init default) and a vault unseal key is available; --no-gpg-sign suppresses it regardless, so it is a no-op only when signing would not have happened anyway. Git's positive -S/--gpg-sign is not exposed; Libra's commit signing is driven by the vault.signing config instead.

libra commit --no-gpg-sign -m "message"

--fixup <COMMIT>

Create a fixup commit whose message is fixup! <target subject>.

libra commit --fixup HEAD~1

--squash <COMMIT>

Create a squash commit whose message is squash! <target subject>.

libra commit --squash abc1234

-C <COMMIT>, --reuse-message <COMMIT>

Reuse the commit message from the specified commit.

libra commit -C HEAD~1

-c <COMMIT>, --reedit-message <COMMIT>

Reuse the commit message from the specified commit. In Git this opens an editor; Libra reuses the message directly when no editor is available.

libra commit -c HEAD~1

--trailer <TRAILER>

Add a trailer line to the commit message. Can be specified multiple times.

libra commit -m "Add feature" --trailer "Reviewed-by: Jane Doe"

--reset-author

Reset the author of the commit to the current user identity. This is the default for new commits; the flag is accepted for Git compatibility.

libra commit --amend --reset-author --no-edit

Common Commands

libra commit -m "Add new feature"
libra commit -m "feat: add login" --conventional
libra commit --amend
libra commit --amend --no-edit
libra commit -a -m "Fix typo"
libra commit -F message.txt
libra commit -s -m "Add feature"
libra commit --allow-empty -m "Trigger CI"
libra commit --dry-run -m "Draft commit"
libra commit --fixup HEAD~1
libra commit -C HEAD~1
libra commit -m "Add feature" --trailer "Reviewed-by: Jane Doe"
libra commit --json -m "Add feature"

Human Output

Default human mode writes the commit summary to stdout.

Normal commit:

[main abc1234] Add new feature
 2 files changed (new: 1, modified: 1, deleted: 0)

Root commit:

[main (root-commit) abc1234] Initial commit
 1 file changed (new: 1, modified: 0, deleted: 0)

--quiet suppresses all stdout output.

Structured Output

libra commit supports the global --json and --machine flags.

  • --json writes one success envelope to stdout
  • --machine writes the same schema as compact single-line JSON
  • both suppress hook stdout/stderr (piped instead of inherited)
  • stderr stays clean on success

Example:

{
  "ok": true,
  "command": "commit",
  "data": {
    "head": "main",
    "branch": "main",
    "commit": "abc1234def5678901234567890abcdef12345678",
    "short_id": "abc1234",
    "subject": "Add new feature",
    "root_commit": false,
    "amend": false,
    "files_changed": {
      "total": 2,
      "new": 1,
      "modified": 1,
      "deleted": 0
    },
    "signoff": false,
    "conventional": null,
    "signed": true
  }
}

Root commit:

{
  "ok": true,
  "command": "commit",
  "data": {
    "head": "main",
    "branch": "main",
    "commit": "abc1234def5678901234567890abcdef12345678",
    "short_id": "abc1234",
    "subject": "Initial commit",
    "root_commit": true,
    "amend": false,
    "files_changed": {
      "total": 1,
      "new": 1,
      "modified": 0,
      "deleted": 0
    },
    "signoff": false,
    "conventional": null,
    "signed": true
  }
}

Amend:

{
  "ok": true,
  "command": "commit",
  "data": {
    "head": "main",
    "branch": "main",
    "commit": "def5678abc1234901234567890abcdef12345678",
    "short_id": "def5678",
    "subject": "Amended message",
    "root_commit": false,
    "amend": true,
    "files_changed": {
      "total": 1,
      "new": 0,
      "modified": 1,
      "deleted": 0
    },
    "signoff": false,
    "conventional": null,
    "signed": true
  }
}

Schema Notes

  • head is the branch name or "detached" for backward compatibility
  • branch is null when HEAD is detached; Some(name) otherwise
  • conventional is true when --conventional was passed and validation succeeded; null when not requested
  • signed is true when vault signing is enabled and the commit was GPG-signed
  • signoff is true when -s / --signoff appended a Signed-off-by trailer

Design Rationale

--conventional flag for conventional commits

Git has no built-in support for commit message format validation; teams rely on external tools like commitlint, husky, or CI checks to enforce Conventional Commits. Libra provides first-class --conventional validation directly in the commit command. This serves two purposes: (1) it gives immediate feedback at commit time rather than delayed feedback in CI, and (2) it enables AI agents (which generate commit messages programmatically) to validate their output without external tooling. The flag is opt-in rather than mandatory, respecting teams that use different commit message conventions.

Vault signing by default instead of manual GPG setup

In Git, commit signing requires configuring user.signingkey, gpg.program, and commit.gpgsign -- a multi-step process that most developers skip. Libra's vault automatically generates and manages a PGP signing key at repository initialization, so commits are signed by default with zero configuration. This makes signed commits the norm rather than the exception, improving supply-chain security for the entire ecosystem. Users who do not want signing can disable it with libra config vault.signing false.

--disable-pre flag

The --disable-pre flag skips only the pre-commit hook while still running the commit-msg hook. This is more granular than Git's --no-verify, which skips all hooks. The use case is when a developer trusts the commit message validation (e.g., conventional commit checks via commit-msg hook) but wants to skip expensive pre-commit checks (e.g., full test suite, large linter runs) during rapid iteration. This separation of concerns is intentional: the commit message is part of the permanent record and should be validated even during quick iterations.

--no-verify to skip hooks

For cases where all hook validation needs to be bypassed (e.g., emergency fixes, WIP commits), --no-verify skips both pre-commit and commit-msg hooks. This aligns with Git's behavior and naming convention. The flag name was chosen for Git compatibility so that developers switching from Git do not need to learn a new flag name.

Parameter Comparison: Libra vs Git vs jj

Parameter / FlagGitjjLibra
Commit with messagegit commit -m "msg"jj commit -m "msg"libra commit -m "msg"
Commit from filegit commit -F fileN/Alibra commit -F file
Amend last commitgit commit --amendjj describe (edits working copy commit)libra commit --amend
Amend without editgit commit --amend --no-editjj describe --no-editlibra commit --amend --no-edit
Auto-stage trackedgit commit -aN/A (automatic tracking)libra commit -a
Allow empty commitgit commit --allow-emptyjj commit --allow-emptylibra commit --allow-empty
Signoff trailergit commit -s / --signoffN/Alibra commit -s / --signoff
GPG sign commitgit commit -S (manual GPG)N/A (no signing)Automatic (vault-backed)
Override authorgit commit --author="..."N/Alibra commit --author="..."
Conventional checkExternal tool (commitlint)N/Alibra commit --conventional
Skip pre-commit onlyN/AN/Alibra commit --disable-pre
Skip all hooksgit commit --no-verifyN/Alibra commit --no-verify
Fixup commitgit commit --fixup=<commit>N/Alibra commit --fixup=<commit>
Squash commitgit commit --squash=<commit>jj squashlibra commit --squash=<commit>
Interactive messagegit commit (opens editor)jj commit (opens editor)libra commit / libra commit -e (opens editor)
Verbose diff in editorgit commit -vN/Alibra commit -v
Reset author dategit commit --reset-authorN/Alibra commit --reset-author
Cleanup modegit commit --cleanup=<mode>N/Alibra commit --cleanup=<mode>
Trailergit commit --trailer="..."N/Alibra commit --trailer="..."
Structured JSON outputN/AN/A--json / --machine
Error hintsMinimalMinimalEvery error type has an actionable hint

Error Handling

Every CommitError variant maps to an explicit StableErrorCode.

ScenarioError CodeExitHint
Index corruptedLBR-REPO-002128"the index file may be corrupted; try 'libra status' to verify"
Failed to save indexLBR-IO-002128--
Nothing to commit (clean)LBR-REPO-003128"use 'libra add' to stage changes"
Nothing to commit (no tracked)LBR-REPO-003128"create/copy files and use 'libra add' to track"
Author identity missingLBR-AUTH-001128"run 'libra config user.name ...' and 'libra config user.email ...'"
No commit to amendLBR-REPO-003128"create a commit before using --amend"
Amend merge commitLBR-REPO-003128"create a new commit instead of amending a merge commit"
Invalid author formatLBR-CLI-002129"expected format: 'Name '"
Message file unreadableLBR-IO-001128--
Empty commit messageLBR-REPO-003128"use -m to provide a commit message"
Tree creation failedLBR-INTERNAL-001128Issues URL
Object storage failedLBR-IO-002128--
Parent commit missingLBR-REPO-002128"the parent commit is missing or corrupted"
HEAD update failedLBR-IO-002128--
Pre-commit hook failedLBR-REPO-003128"use --no-verify to bypass the hook"
Conventional commit invalidLBR-CLI-002129"see https://www.conventionalcommits.org for format rules"
Vault signing failedLBR-AUTH-001128"check vault configuration with 'libra config --list'"
Auto-stage failedLBR-IO-001128--
Staged changes computationLBR-REPO-002128"failed to compute staged changes"

Compatibility Notes

  • libra commit opens the editor to compose the message when no -m/-F/-C source is given (and --no-edit is absent), and -e/--edit always opens it. The editor is resolved as $GIT_EDITOR → core.editor → $VISUAL → $EDITOR → vi. An explicitly configured editor runs even without a TTY; the vi fallback requires an interactive terminal. Without a TTY and without a configured editor, a commit needing a message aborts (it never hangs).
  • -v/--verbose appends the staged diff to the editor template (below a # ----- >8 ----- scissors line); the diff is stripped on save and never enters the commit message. When no editor is opened, -v prints the staged diff to stderr.
  • jj does not have a traditional commit command with staging; jj commit finalizes the working copy commit
  • --fixup and --squash are supported (autosquash markers); --cleanup=<mode> controls comment/scissors stripping
  • Vault signing replaces Git's commit.gpgsign and user.signingkey configuration

libra commit-tree

Command reference for `libra commit-tree`

libra completions

Command reference for `libra completions`

On this page

SynopsisDescriptionOptions-m, --message <MESSAGE>-e, --edit-t, --template <FILE>-v, --verbose--no-edit-F, --file <FILE>--amend--no-edit--conventional-a, --all-s, --signoff--allow-empty--disable-pre--no-verify--author <AUTHOR>--cleanup <MODE>--dry-run--porcelain--status / --no-status--no-gpg-sign--fixup <COMMIT>--squash <COMMIT>-C <COMMIT>, --reuse-message <COMMIT>-c <COMMIT>, --reedit-message <COMMIT>--trailer <TRAILER>--reset-authorCommon CommandsHuman OutputStructured OutputSchema NotesDesign Rationale--conventional flag for conventional commitsVault signing by default instead of manual GPG setup--disable-pre flag--no-verify to skip hooksParameter Comparison: Libra vs Git vs jjError HandlingCompatibility Notes