Gitslice docs

Lazy Workspaces

Mount a slice instead of checking it out. Only the listing is fetched up front; a file's content arrives the first time something reads it, and your edits stay on your machine until you create a changeset. Every gs command works as it does in a checkout.

When to use one

  • Mount (gs init --lazy) when a task touches a part of a large slice: an agent fixing one service, a review, a quick edit. The workspace is ready in seconds, and what it costs follows what is read, not the size of the slice.
  • Check out (gs init) when you will read and build nearly everything, need the files with no FUSE (Windows, a container without /dev/fuse), or want plain disk speed for every read.

On Ryujinx_Neo (4,508 files, 58.6 MB) a mount was ready in 2.6 s where a full checkout took 8 s. The time to mount grows with the number of files, not their size. Benchmarks and method: design/28_benchmarks.md.

Start

Linux or macOS, with FUSE (see Requirements below).

gs init --lazy acme/payments ~/work/payments   # mounts; fetches the listing only
cd ~/work/payments
$EDITOR acme/payments/charge.go                 # fetched when opened
gs status                                       # your edits, as in any workspace
gs create --all --message "payments: retry declined charges" --submit

The mount survives as a workspace: gs unmount <dir> stops serving it with its edits kept, and gs mount <dir> brings it back after an unmount or a reboot. gs mount list shows every lazy workspace on the machine, and gs mount discard <dir> deletes an unmounted one with its edits. One background process serves all of them and exits when the last is unmounted.

How files are fetched

  • Listing and metadata: ls, stat and directory walks are answered from the listing, with no network.
  • First read: a file is fetched the first time something opens it, together with the small files beside it (under 64 KiB, in the same request), since reading one file of a folder usually means reading more. Each first read is a round trip to the server.
  • Walks of the tree: when reads follow the tree in order, as grep -r, rg, a build or an indexer do (in either direction), the mount fetches the files ahead of the reader. A cold rg over Ryujinx_Neo went from 175 s to 14 s with it. Scattered reads fetch nothing extra. GS_READAHEAD=off turns it off.
  • Everything, ahead of time: gs fetch (or gs fetch <path>...) fetches in batches, in parallel. It is still the fastest way to prepare for work that reads everything, and it is what makes a workspace readable offline.
  • Known patterns: gs init --lazy <slice> <dir> --prefetch 'acme/app/**/*.go' fetches matching files in the background, now and after every sync.
  • The cache: fetched content is kept in a cache shared by every workspace on the machine, so a second mount of the same slice reads what the first fetched.

Where your edits live

Writes go to the workspace's local layer, on your machine. Nothing is uploaded until gs create or gs modify, which upload only what you changed. Edit with any tool; gs status and gs diff read the local layer instead of scanning the tree, so they are instant at any size.

  • Undo: gs restore <path>... or gs restore --all drops local edits, so the slice's content shows again.
  • Moving the base: gs sync and switching between changesets (gs switch, gs up, gs down) move the mount without rewriting or fetching files: files nobody changed take the new base, and new content is fetched when read.

Checkpoints, rewind and fork

A checkpoint saves the workspace's edits on this machine, to come back to. Nothing is uploaded. Agents use them to try an approach and back out of it cheaply.

gs checkpoint -m "tests pass, before the refactor"
gs checkpoint list           # newest first, with numbers
gs rewind 3                  # put the edits back as they were at checkpoint 3
gs rewind                    # back to the newest one that differs from now
gs fork 3 ~/work/payments-b  # open checkpoint 3 as a second workspace
  • Automatic: gs takes a checkpoint by itself before gs sync, gs switch, gs restore and gs rewind replace your files, keeping the last 50. Ones you take with gs checkpoint are kept until the workspace is deleted.
  • Undoable: a rewind first checkpoints what it replaces, so another rewind undoes it.
  • Fork: mounts a new lazy workspace showing the checkpoint, on the base it was taken on, so two approaches can be worked side by side. A checkpoint from before a sync moved the workspace is opened with gs fork, not rewound to.

Checkpoints work in lazy workspaces only, for now.

Requirements

  • Linux: FUSE 3: /dev/fuse and fusermount3 (the fuse3 package). No root needed.
  • macOS: macFUSE. After installing it, allow its system extension in System Settings, Privacy & Security, and restart; until then a mount waits and then fails with a hint.
  • Windows: not supported; use gs init.

When something is wrong

  • gs doctor checks the whole setup, including whether a test mount works on this machine.
  • gs mount status [dir] shows the workspace's base, how much was fetched, and the last errors, with the path and the reason.
  • Offline: reads the cache can answer, and every edit, keep working. A read that needs an unreachable server fails after a few seconds of retrying, and the next ones fail at once for a while, so a build does not hang on each file. Run gs fetch beforehand to work offline.
  • A dead mount: if the process serving it was killed, fusermount3 -u <dir> (Linux) or umount <dir> (macOS) clears it, and gs mount <dir> brings the workspace back, edits included.

Understand the model

Workspaces, changesets, patchsets and submit, and how they fit together.

CLI reference

Every command, including gs mount, gs fetch and gs checkpoint.