Shelving
Subversion has no git stash. Shelving exists in svn only as an experimental feature
that standard builds are compiled without, so revision provides its own: a shelf of
change sets taken out of the working copy and kept beside it, ready to be put back.
A shelf entry holds the patch that reproduces a set of changes, verbatim copies of the unversioned files no patch can describe, and the base revision, file states and changelist memberships needed to restore them faithfully.
Picking what to shelve
Section titled “Picking what to shelve”v in the Files panel holds the selection for the next shelve. A tick appears beside each held row, and the hint bar counts what is held.
╭─ [1] Status ─────────────────╮╭─ [0] Diff ───────────────────────────────────╮ │Root /home/alice/work/wc ││Loading diff… │ │Source /home/alice/work/wc ││ │ │CWD /home/alice/work/wc ││ │ │Branch trunk ││ │ │Revision r42 ││ │ │ ││ │ ╰──────────────────────────────╯│ │ ╭─ [2] ─ Changes ─── Changelist╮│ │ │ ▾ / ┃││ │ │ ▾ cmd/ ┃││ │ │ M main.go │││ │ │> ✓▾ internal/ │││ │ ╰────────────────── 1 of 4 ────╯│ │ ╭─ [3] Log ────────────────────╮│ │ │ Rev Author Message ││ │ │ │╰──────────────────────────────────────────────╯ │ │╭─ Command Log ────────────────────────────────╮ │ ││No svn commands run yet. │ ╰──────────────────────────────╯│ │ ╭─ [4] Shelf ──────────────────╮│ │ │ ││ │ ╰──────────────────────────────╯╰──────────────────────────────────────────────╯ 2 files picked · z shelve · esc clear · space stage · a add · v pick · …
| Where you press it | What is held |
|---|---|
| A file in the Changes tree | that file |
| A directory row | everything shelvable beneath it |
| A changelist row, in the Changelists view | every file in that changelist |
| A file inside a drilled-in changelist | that file |
Pressing v again lets the selection go, and esc releases everything. Picks are held by path rather than by row, so they survive a reload, a filter and a rebuild — and a pick whose file has since been committed simply drops out.
Shelving
Section titled “Shelving”z takes what is held. A prompt asks what to call the entry; leaving it blank names it after the set it came from.
With nothing held, z means the whole working copy, and asks before taking it.
Once the entry is written, revision reverts the files it captured and removes those that
were only scheduled additions — a revert un-schedules an add but leaves the file where it
was. The Changes view empties, and the entry appears in the Shelf panel.
What a shelf cannot carry
Section titled “What a shelf cannot carry”Two things are left in the working copy rather than lost, and named in the toast that follows:
- Binary files.
svn diffwill not express one as text — it printsCannot display: file marked as a binary type.and no content — so a shelf that reverted them would destroy them. They stay put. - Unversioned directories and symlinks. Neither has bytes of its own to copy.
Conflicted files are not offered for shelving at all. A conflict needs deciding rather than setting aside, and reverting one throws the merge away — resolve it first.
A move is carried as a deletion and an addition. The content survives in full, but svn’s record that one came from the other does not.
The Shelf panel
Section titled “The Shelf panel”The Shelf panel is the fourth numbered panel, below Log. 4 focuses it, and it grows to show its whole list while it has focus, taking the room from the Log panel above it — the Files panel does not move. It stays open while you read an entry’s patch in Main, and collapses again when another side panel takes over.
Each row is the entry’s name, how many files it holds, and when it was shelved. Selecting one shows its patch in Main. / filters the list by name.
╭─ [1] Status ─────────────────╮╭─ [0] Shelved diff ───────────────────────────╮
│Root /home/alice/work/wc ││Index: cmd/main.go │
│Source /home/alice/work/wc ││@@ -1,3 +1,4 @@ │
│CWD /home/alice/work/wc ││ func main() { │
│Branch trunk ││+ setup() │
│Revision r42 ││ run() │
│ ││ } │
╰──────────────────────────────╯│ │
╭─ [2] ─ Changes ─── Changelist╮│ │
│ ▾ / ││ │
│ M loose.txt ││ │
│ ││ │
│ ││ │
╰────────────────── 1 of 1 ────╯│ │
╭─ [3] Log ────────────────────╮│ │
│ Rev Author Message ││ │
╰──────────────────────────────╯╰──────────────────────────────────────────────╯
╭─ [4] Shelf ──────────────────╮╭─ Command Log ────────────────────────────────╮
│> ▣ wip refactor (3 files · 20││No svn commands run yet. │
│ ▣ spike (1 file · 2026-08-19││ │
│ ││ │
│━━━━━━━━━━━━━━━━━━━━──────────││ │
╰────────────────── 1 of 2 ────╯╰──────────────────────────────────────────────╯
enter apply · p pop · d drop · n rename · z shelve · / filter · ? help | Key | Action |
|---|---|
| enter | Apply — merge back, keep the entry |
| p | Pop — merge back and take the entry off the shelf |
| d | Drop the entry |
| n | Rename the entry |
With allowMouse on, clicking a row selects it and
double-clicking one applies it — the prompt enter opens, never the pop, so
a mis-aimed click costs a revert rather than the only copy of the change set.
An entry’s patch is read rather than worked in: e opens nothing from it, and neither does double-clicking one of its lines. It describes the files as they were when they were set aside, not as the working copy holds them now.
Restoring
Section titled “Restoring”Both enter and p ask first, and put the entry’s patch through the same checks a saved patch goes through: a shelf whose files are not in this directory is refused, as is one svn says would land nothing at all.
Unversioned files are copied back from the bytes the entry holds. A path that is already taken is reported rather than written over — what is sitting there is your current work — and the entry keeps its copy either way.
Changelist membership is replayed afterwards, since no patch records it: files return to the changelists they were shelved from.
Pop only drops the entry when the whole of it went back. While a hunk is sitting in a
.rej file or an unversioned file could not be placed, the shelf is the only remaining
copy of what did not make it, so it is kept and the toast says so.
Where shelves are kept
Section titled “Where shelves are kept”In .#revision-shelves/ at the root of the working copy — one directory per entry, holding
meta.json, changes.patch and any unversioned files it carries.
The name is doing real work. .#* is one of Subversion’s built-in global-ignores
patterns, so the store stays out of svn status, svn diff and svn add without a
property being set on your working copy and without a line of configuration. There is
nothing to configure, and nothing to add to an ignore list.
svn update, svn cleanup, svn revert, svn switch and even
svn cleanup --remove-unversioned all leave it alone.