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 stash

Command reference for `libra stash`

Stash the changes in a dirty working directory away.

Synopsis

libra stash push [-m <message>] [-u | -a] [-k | --keep-index] [-- <pathspec>...]
libra stash pop [<stash>]
libra stash list
libra stash apply [<stash>]
libra stash drop [<stash>]
libra stash show [<stash>] [-p | --patch] [--name-only | --name-status]
libra stash branch <branch> [<stash>]
libra stash clear [--force]

Description

libra stash saves your local modifications to a new stash entry and reverts the working directory to match HEAD. By default, stash push records tracked index/worktree changes and leaves untracked files alone. Use -u / --include-untracked to include visible untracked files, or -a / --all to include ignored files too. Pass -- <pathspec>... (file or directory paths; . selects the whole tree) to stash only the changes to those paths, leaving every other change in the working tree. A pathspec cannot be combined with -u/-a/-k. The modifications can be restored later with libra stash pop or libra stash apply, which replay the stash onto the CURRENT working tree (not HEAD) — so any unrelated uncommitted change you made in the meantime, including the paths a pathspec push left behind, is preserved. Default apply / pop leave the current index intact, so restored tracked changes appear as unstaged working-tree changes; Git's --index restore mode is not exposed yet. If stash push is run on a clean working tree and no requested untracked files exist, it exits successfully as a no-op and reports that there are no local changes to save.

Stash entries are stored as specially-structured commit objects under .libra/refs/stash, with a flat-file list tracking the stash stack. Each stash captures both the index state and worktree state at the time of creation.

Options

Subcommands

push

Save your local modifications to a new stash and clean the working directory.

OptionShortLongDescription
Message-m--messageOptional descriptive message for the stash entry. If omitted, a default "WIP on <branch>: <short-hash> ..." message is generated.
Include untracked-u--include-untrackedInclude visible untracked files in the stash and remove them from the worktree. Ignored files remain in place.
No include untracked--no-include-untrackedDo not include untracked files (the default), countermanding an earlier -u/--include-untracked (last one wins). Untracked files are excluded by default, so on its own this is a no-op.
Include all-a--allInclude visible untracked and ignored files in the stash, then remove them from the worktree.
Keep index-k--keep-indexKeep staged changes in the index and restore the worktree to the staged content, removing only unstaged deltas.
# Save with default message
libra stash push

# Save with a descriptive message
libra stash push -m "work in progress on feature X"

# Include visible untracked files
libra stash push -u

# Include ignored files too
libra stash push -a

# Stash only unstaged deltas while keeping staged content ready to commit
libra stash push --keep-index

# Stash only the changes to specific paths (here a file and a directory),
# leaving every other change in the working tree
libra stash push -- src/main.rs docs/

pop

Apply the top stash entry and remove it from the stash list. Equivalent to apply followed by drop. By default, restored tracked changes are written to the working tree only and are not staged.

ArgumentDescription
<stash>Stash reference, e.g. stash@{1}. Defaults to stash@{0} (the most recent stash).
# Pop the latest stash
libra stash pop

# Pop a specific stash
libra stash pop stash@{2}

list

List all stash entries with their index, message, and stash ID.

libra stash list

apply

Apply a stash entry without removing it from the stash list. Useful when you want to apply the same stash to multiple branches. By default, restored tracked changes are written to the working tree only and are not staged.

ArgumentDescription
<stash>Stash reference, e.g. stash@{1}. Defaults to stash@{0}.
libra stash apply
libra stash apply stash@{1}

drop

Remove a single stash entry from the stash list without applying it.

ArgumentDescription
<stash>Stash reference, e.g. stash@{1}. Defaults to stash@{0}.
libra stash drop
libra stash drop stash@{1}

show

Show the file-level changes recorded in a stash entry.

Argument / FlagDescription
<stash>Stash reference, e.g. stash@{1}. Defaults to stash@{0}.
-p / --patchShow the stashed changes as a unified diff (patch) instead of the file-level summary.
--name-onlyShow only the changed file names, one per line.
--name-statusShow file names prefixed with the status code (A / M / D).

--name-only and --name-status are mutually exclusive in human render mode; the JSON envelope always carries the full files list with status, regardless of which hint is set. With -p/--patch, the human output is the unified diff (no summary footer) and the JSON envelope adds a patch field (absent otherwise).

# File-level summary of stash@{0}
libra stash show

# Inspect a specific stash entry
libra stash show stash@{1}

# Show the stashed changes as a unified diff
libra stash show -p

# File names only
libra stash show --name-only

branch

Create a new branch from a stash entry, apply the stash on it, then drop the entry. Useful when a stash applies cleanly only on a branch that no longer exists, or when you want to resume the stashed work as a normal branch.

ArgumentDescription
<branch>Name of the new branch to create. Required.
<stash>Stash reference, e.g. stash@{1}. Defaults to stash@{0}.
# Branch off the latest stash and drop it
libra stash branch hotfix

# Branch off a specific stash
libra stash branch hotfix stash@{2}

clear

Remove every stash entry. Outside --json / --machine mode, --force is required to prevent accidental data loss.

FlagDescription
--forceSkip the confirmation requirement. Mandatory in human mode; bypassed automatically in JSON / machine mode.
# Human mode (refuses without --force)
libra stash clear --force

# JSON mode (--force not required)
libra stash clear --json

Global Flags

FlagDescription
--jsonEmit structured JSON output
--quietSuppress human-readable output

Common Commands

# Save current changes
libra stash push

# Save with a message
libra stash push -m "work in progress on feature X"

# Save tracked changes plus visible untracked files
libra stash push -u

# Save unstaged deltas without disturbing staged content
libra stash push --keep-index

# List stashes
libra stash list

# Apply and remove the latest stash
libra stash pop

# Apply without removing
libra stash apply

# Drop a specific stash
libra stash drop stash@{1}

# JSON output for scripting
libra stash list --json

Human Output

stash push (with changes):

Saved working directory and index state WIP on main: abc1234 ...

stash push (clean working tree):

No local changes to save

stash list:

stash@{0}: WIP on main: abc1234 initial commit
stash@{1}: On main: work in progress on feature X

stash pop / stash apply:

On branch main
Changes restored from stash@{0}

stash drop:

Dropped stash@{0} (abc1234...)

Structured Output (JSON)

When --json is passed, all subcommands produce a JSON envelope:

{
  "command": "stash",
  "data": {
    "action": "push",
    "message": "WIP on main: abc1234 ...",
    "stash_id": "..."
  }
}

When -u, -a, or --keep-index is used, the push envelope adds only the relevant fields:

{
  "command": "stash",
  "data": {
    "action": "push",
    "message": "WIP on main: abc1234 ...",
    "stash_id": "...",
    "included_untracked": 2,
    "kept_index": true
  }
}

On a clean working tree, stash push --json returns:

{
  "command": "stash",
  "data": { "action": "noop", "message": "No local changes to save" }
}

The data.action field is one of: noop, push, pop, apply, drop, list, show, branch, clear.

list JSON schema

{
  "command": "stash",
  "data": {
    "action": "list",
    "entries": [
      { "index": 0, "message": "WIP on main: ...", "stash_id": "abc1234..." }
    ]
  }
}

pop / apply JSON schema

{
  "command": "stash",
  "data": {
    "action": "pop",
    "index": 0,
    "stash_id": "abc1234...",
    "branch": "main"
  }
}

drop JSON schema

{
  "command": "stash",
  "data": {
    "action": "drop",
    "index": 0,
    "stash_id": "abc1234..."
  }
}

show JSON schema

{
  "command": "stash",
  "data": {
    "action": "show",
    "stash": "stash@{0}",
    "stash_id": "abc1234...",
    "files": [
      { "path": "src/foo.rs", "status": "M" }
    ],
    "files_changed": {
      "total": 1,
      "added": 0,
      "modified": 1,
      "deleted": 0
    }
  }
}

The structured envelope always emits the full files list. The --name-only / --name-status flags only affect human render output.

branch JSON schema

{
  "command": "stash",
  "data": {
    "action": "branch",
    "branch": "hotfix",
    "stash": "stash@{0}",
    "stash_id": "abc1234...",
    "applied": true,
    "dropped": true
  }
}

clear JSON schema

{
  "command": "stash",
  "data": {
    "action": "clear",
    "cleared_count": 3
  }
}

Design Rationale

How untracked and ignored files are stored

stash push -u and stash push -a use a third stash parent for the untracked/all snapshot, matching Git's object topology. stash apply and stash pop restore those files as untracked worktree files. If a local file would be overwritten during restore, the apply/pop operation fails and keeps the stash entry intact.

How pop / apply treat the index

Default stash pop and stash apply restore tracked content to the working tree while leaving the current index unchanged. A change that was staged when stashed comes back as an unstaged working-tree edit unless a future --index mode is added. This matches Git's default stash pop / stash apply behavior and prevents a later libra commit from committing restored stash content before the user runs libra add.

How --keep-index works

stash push --keep-index stores the same stash metadata as a normal push, then writes the saved index back and restores the worktree to the index state. For a mixed file with both staged and unstaged edits, the staged content remains in the index and worktree, while the unstaged delta is saved in the stash.

Why a curated subcommand model?

Git's stash has grown organically and supports git stash as a shorthand for git stash push, plus git stash save (deprecated) and the plumbing pair git stash create / git stash store. Libra exposes the eight subcommands users actually reach for in practice: push, pop, list, apply, drop, show, branch, and clear. The plumbing pair (create / store) and the save shorthand are deferred — see docs/development/commands/_compatibility.md sections D8 and D9. This keeps the surface aligned with stock Git for everyday workflows while leaving rarely-used plumbing out of the maintained surface.

Why stash@{N} syntax instead of plain indices?

Libra preserves Git's stash@{N} reference syntax for familiarity. Users migrating from Git can use the same muscle memory. The parser also accepts bare integers in some contexts, but the canonical form remains stash@{N}.

Parameter Comparison: Libra vs Git vs jj

ParameterLibraGitjj
Push (save changes)stash pushstash push / stash save (deprecated)N/A (no stash; use jj new to shelve)
Message-m <message>-m <message>N/A
Keep index--keep-index--keep-index / --no-keep-indexN/A
Include untracked-u / --include-untracked-u / --include-untrackedN/A
No include untracked--no-include-untracked (countermands -u)--no-include-untrackedN/A
Include all (ignored too)-a / --all-a / --allN/A
Pathspec (partial stash)stash push -- <pathspec>... (file/dir paths, . = whole tree; not combinable with -u/-a/-k → LBR-CLI-002; no match → LBR-CLI-003)stash push [--] <pathspec>...N/A
Popstash pop [ref]stash pop [--index] [<stash>]N/A
Applystash apply [ref]stash apply [--index] [<stash>]N/A
Dropstash drop [ref]stash drop [<stash>]N/A
Liststash liststash list [<log-options>]N/A
Show file-level summarystash show [<stash>] [--name-only | --name-status]stash show [<stash>]N/A
Show stash as a patchstash show -p | --patch [<stash>]stash show -p [<stash>]N/A
Create branch from stashstash branch <branch> [<stash>]stash branch <branch> [<stash>]N/A
Clear all stashesstash clear [--force]stash clearN/A
Plumbing create/storeNot supported (deferred — see compatibility/declined.md D8/D9)stash create / stash storeN/A
JSON output--jsonNot supportedN/A
Quiet mode--quiet-q / --quietN/A

Note: jj does not have a stash command. Its change-based model allows creating anonymous changes with jj new that serve a similar purpose to stashing.

Error Handling

CodeCondition
LBR-REPO-001Not a libra repository
LBR-REPO-003No initial commit
LBR-CLI-002Invalid stash reference syntax
LBR-CLI-003Stash does not exist
LBR-CONFLICT-001Merge conflict during stash apply

libra sparse-view

Command reference for `libra sparse-view`

libra stats

Command reference for `libra stats`

On this page

SynopsisDescriptionOptionsSubcommandspushpoplistapplydropshowbranchclearGlobal FlagsCommon CommandsHuman OutputStructured Output (JSON)list JSON schemapop / apply JSON schemadrop JSON schemashow JSON schemabranch JSON schemaclear JSON schemaDesign RationaleHow untracked and ignored files are storedHow pop / apply treat the indexHow --keep-index worksWhy a curated subcommand model?Why stash@{N} syntax instead of plain indices?Parameter Comparison: Libra vs Git vs jjError Handling