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 blame

Command reference for `libra blame`

Trace each line of a file to the commit that last introduced it.

Synopsis

libra blame <file> [<commit>] [-L <range>]

Description

libra blame annotates each line of a file with the commit hash, author name, date, and line number of the commit that last modified that line. It walks the commit history from the specified revision (defaulting to HEAD) backward through parent commits, using diff operations to attribute lines to the earliest commit that introduced them.

The output format matches Git's blame format for familiarity: a short hash, author name (truncated to 15 characters), date, line number, and line content on each line.

For large files, the -L option restricts output to a specific line range, reducing both computation time and output volume.

Options

OptionShortLongDescription
Filepositional (required)The file to blame. Must exist in the specified revision.
Commitpositional (optional)The revision to start blame from. Defaults to HEAD.
Line range-L-L <RANGE>Restrict blame to a line range. See formats below.
Show email-e--show-emailShow the author email (as <email>) instead of the author name in the default output.
Long hash-lShow the full commit hash instead of the abbreviated one.
Suppress-sSuppress the author name and timestamp columns (show only hash + line).
Show name-f--show-nameShow the filename after the hash column on each line. Libra does not follow renames/copies, so it is the blamed file on every line. Human output only (porcelain already prints filename).
Raw time-tShow the raw author timestamp (epoch seconds) instead of a formatted date.
Abbrev--abbrev <N>Use N hex digits for the abbreviated commit hash (ignored with -l).
Root--rootDo not treat root commits as boundaries. Accepted no-op: Libra's blame never prefixes boundary/root commits with ^, so root commits already appear as normal commits.
Ignore whitespace-w--ignore-whitespaceIgnore whitespace when comparing the parent's and child's versions of a line, so a whitespace-only change is attributed to the older commit. Matches Git's -w (ignore-all-whitespace) semantics.
Porcelain-p--porcelainMachine-readable porcelain output (commit metadata once per commit).
JSON--jsonEmit structured JSON output.
Quiet--quietValidate inputs but suppress all blame output.

Line Range Formats (-L)

Each endpoint of -L may be a line number or a /regex/; a single endpoint spans to the end of the file (matching Git):

FormatMeaningExample
NFrom line N to the end of the file-L 10
N,MLines N through M (inclusive)-L 10,20
N,+CC lines starting at line N-L 10,+5 (lines 10-14)
/regex/From the first line matching the regex to the end of the file-L '/fn main/'
/start/,/end/From the first /start/ match to the first /end/ match at or after it-L '/fn main/,/^}/'
/start/,M or N,/end/Mix a regex endpoint with a line number-L 10,/^}/

Line numbers are 1-based. Out-of-range values, and a /regex/ that matches no line, produce an error.

# Blame from line 42 to the end of the file
libra blame -L 42 src/main.rs

# Blame a range
libra blame -L 10,20 src/main.rs

# Blame from a regex match to a regex match
libra blame -L '/fn main/,/^}/' src/main.rs

# Blame 5 lines starting at line 100
libra blame -L 100,+5 src/main.rs

Common Commands

# Blame a file at HEAD
libra blame src/main.rs

# Blame at a specific commit
libra blame src/main.rs abc1234

# Blame lines 10-20
libra blame -L 10,20 src/main.rs

# Blame 5 lines from line 10
libra blame -L 10,+5 src/main.rs

# Ignore whitespace-only changes when attributing lines
libra blame -w src/main.rs

# JSON output for agents
libra --json blame src/main.rs

Human Output

abc12345 (Author Name     2026-03-30 10:00:00 +0800 1) line content
def67890 (Other Author    2026-03-28 14:30:00 +0800 2) another line
abc12345 (Author Name     2026-03-30 10:00:00 +0800 3) third line

Each line shows:

  • Short hash (8 characters): the commit that last changed this line.
  • Author name (padded to 15 characters, truncated with ... if longer).
  • Date: formatted in the local timezone as YYYY-MM-DD HH:MM:SS +ZZZZ.
  • Line number: 1-based line number in the file.
  • Content: the actual line content.

--quiet validates the revision, file, and line range but suppresses all output. This is useful for scripted checks ("does this file exist at this revision?").

Output is automatically paged when connected to a terminal.

Structured Output (JSON)

{
  "ok": true,
  "command": "blame",
  "data": {
    "file": "tracked.txt",
    "revision": "abc123...",
    "lines": [
      {
        "line_number": 1,
        "short_hash": "abc12345",
        "hash": "abc123...",
        "author": "Test User",
        "date": "2026-03-30T10:00:00+00:00",
        "content": "tracked"
      }
    ]
  }
}

The revision field contains the full commit hash that was used as the blame starting point. Each line entry includes both the short_hash (8 characters) and full hash for programmatic use.

When the file is empty, the lines array is empty and human output shows "File is empty".

Design Rationale

Why no --reverse?

Git's blame --reverse shows the last revision in which a line existed, walking forward in history instead of backward. This is useful for finding when a line was removed, but it requires forward-history traversal which is computationally expensive and architecturally different from normal blame. Libra omits this to keep the blame implementation simple and fast. To find when a line was removed, use libra log -p -- <file> and search for the deletion.

Line range formats

Libra's -L supports numeric ranges (N, N,M, N,+C) and /regex/ endpoints (/regex/, /start/,/end/, and regex mixed with line numbers), matching Git; a single endpoint spans to the end of the file. Git's -L :<funcname> function-name selection is not yet supported, as it depends on language-specific configuration (the .gitattributes diff driver).

Why default to HEAD instead of working tree?

Git's blame defaults to HEAD and requires git blame --contents <file> to blame the working-tree version. Libra follows the same convention: blame always operates on committed content. This ensures reproducible results -- the same command with the same commit always produces the same output, regardless of working-tree state.

Why positional commit argument instead of a flag?

The commit argument is positional (second argument after the file path) rather than a flag like --commit or --rev. This matches Git's syntax for familiarity and keeps the common case (libra blame file.rs) concise. Since the file path is always the first positional argument, there is no ambiguity.

Parameter Comparison: Libra vs Git vs jj

ParameterLibraGitjj
File<file> (positional, required)<file> (positional, required)N/A (jj has no blame; use jj annotate)
Revision<commit> (positional, default HEAD)<rev> (positional, default HEAD)-r <revision> (in jj annotate)
Line range (numeric)-L N,M / -L N,+C / -L N-L <start>,<end>N/A
Line range (regex)-L /regex/ / -L /start/,/end/-L /regex/N/A
Line range (funcname)Not supported-L :<funcname>N/A
Reverse blameNot supported--reverseN/A
Show email-e / --show-email (default human output)-e / --show-emailN/A
Long hash-l-lN/A
Suppress author/date-s-sN/A
Show filename-f / --show-name-f / --show-nameN/A
Show timestamp-t (raw epoch; formatted by default)-t (raw timestamp)N/A
Abbrev length--abbrev <N>--abbrev=<N>N/A
Don't treat root as boundary--root (no-op; root already shown as normal)--rootN/A
Ignore whitespace-w / --ignore-whitespace (ignore-all-whitespace)-wN/A
Porcelain format-p / --porcelain / --line-porcelain (no original line numbers, boundary, or previous metadata)-p / --porcelain / --line-porcelainN/A
Incremental outputNot supported--incrementalN/A
Score thresholdNot supported-M / -C (move/copy detection)N/A
Ignore revisionsNot supported--ignore-rev / --ignore-revs-fileN/A
Working tree contentsNot supported--contents <file>N/A
Date formatNot supported (fixed)--date <format>N/A
EncodingNot supported--encoding <encoding>N/A
JSON output--jsonNot supportedNot supported
Quiet mode--quietNot supportedN/A
PagerAutomaticConfigurableConfigurable

Error Handling

ScenarioStableErrorCodeExit
Outside a repositoryLBR-REPO-001128
Invalid revision or missing fileLBR-CLI-003129
Invalid -L rangeLBR-CLI-002129
Failed to read the commit or objectLBR-REPO-002128

libra bisect

Command reference for `libra bisect`

libra branch

Command reference for `libra branch`

On this page

SynopsisDescriptionOptionsLine Range Formats (-L)Common CommandsHuman OutputStructured Output (JSON)Design RationaleWhy no --reverse?Line range formatsWhy default to HEAD instead of working tree?Why positional commit argument instead of a flag?Parameter Comparison: Libra vs Git vs jjError Handling