6. Targeting slices¶
Bare push and pull move everything bound. Real repositories rarely want
that every time — this chapter narrows a transfer to one unit, one stage,
one sample, or a plan you merely want to look at.
Units and --stage¶
Positional unit IDs (with --stage to say where they live) target exactly
one slice:
Everything is still synced from chapter 5, so forest correctly does nothing — the targeting worked, there was just nothing to move.
Dry runs¶
--dry-run prints the transfer plan without moving a byte. Drop a draft
file into plot 1 and ask what a push would do:
echo 'draft — do not sync' > data/raw/plot-01/scratch-notes.txt
forest push plot-01 --stage raw --dry-run
Ad-hoc excludes¶
--exclude drops files matching a glob — relative to each unit's
directory — for this invocation only:
Back to 2 files: the draft is excluded. --exclude can repeat, and it
composes with the always-on OS-junk skip list. Clean up the draft before
moving on:
Manifest IDs: name the sample, not the unit¶
Units are storage-shaped (plot-01); your domain speaks in sample IDs.
A manifest — a plain CSV committed next to your code — maps one to the
other:
cat > samples.csv <<'EOF'
sample_id,raw_unit,processed_unit
S-001,plot-01,processed
S-002,plot-02,processed
EOF
Then tell the checkout about it by appending a manifest: section to
.forest/checkouts/survey/forest.yaml:
manifest:
file: samples.csv
id_column: sample_id
stage_columns:
raw: raw_unit
processed: processed_unit
id_column is the column holding your IDs; stage_columns maps each stage
to the column naming that stage's unit.
The one hand-edit
Forest's onboarding never requires hand-written config — the manifest is
the exception, an opt-in feature with no CLI command (yet). It lives in
the shared forest.yaml, so the whole team gets it from git.
Now --id resolves a sample to its units across all mapped stages:
synced:origin raw/plot-01 73 B pushed 2026-07-02 22:32
synced:origin raw/plot-01 73 B pulled 2026-07-02 22:32
synced:origin processed/processed 44 B pushed 2026-07-02 22:32
synced:origin processed/processed 44 B pulled 2026-07-02 22:32
One sample ID → the raw plot and its processed output, never the
unrelated plot-02. --id works on push, pull, status, and ls.
See the whole graph: forest flow¶
forest flow emits a Mermaid diagram of the
active checkout — checkout, manifest, stages, remote — straight to stdout
(dry-run only; it never touches the network):
flowchart LR
project["project: survey"]
manifest["manifest: samples.csv"]
sync_state[".forest/sync_state.json"]
remote_origin["remote: origin<br/>/home/user/forest-remote"]
stage_processed["stage: processed<br/>path: /home/user/field-notes/data/processed"]
stage_raw["stage: raw<br/>path: /home/user/field-notes/data/raw"]
manifest -->|sample_id| project
project --> stage_processed
manifest -->|processed_unit| stage_processed
project --> stage_raw
manifest -->|raw_unit| stage_raw
Paste that into any Markdown file that renders Mermaid — like this site:
flowchart LR
project["project: survey"]
manifest["manifest: samples.csv"]
stage_processed["stage: processed"]
stage_raw["stage: raw"]
manifest -->|sample_id| project
project --> stage_processed
manifest -->|processed_unit| stage_processed
project --> stage_raw
manifest -->|raw_unit| stage_raw
forest flow --id S-001 expands one sample down to its units and resolved
paths; --stage raw expands a single stage; --direction TD flips the
layout and --output PATH writes to a file instead of stdout.
Recap: positional units + --stage for one slice; --dry-run to look
before you leap; --exclude for unit-relative ad-hoc globs; a manifest CSV
gives you domain IDs; flow draws the map.
Next: see all of this running in the wild — dogfood.