stol is a suite of tools that make it easy to create and manage git
worktrees. It uses reflinks to make worktree creation fast and cheap even on
huge monorepos.
In order to use stol, you need a Linux filesystem that supports reflinks. The root filesystem in most Linux installations does not support reflinks, so most users will have to create a new fileystem in order to use stol.
There are two ways to provide one.
- As a disk image: create a large file on your existing disk, format it as XFS,
and mount it.
stol create-imagesets this up. - As a dedicated disk: format a spare physical disk as XFS and mount it.
stol format-drivesets this up.
stol contains helpers for both options.
Although stol has only been tested on XFS, it may be possible to use other filesystems like btrfs.
Building stol requires liburing, a C compiler, and make
sudo apt install liburing-dev gcc makeAt runtime stol uses:
git: requiredxfsprogs: required for most users. supportsstol create-imageandstol format-drivesgdisk: required only forstol format-drivegh: optional, supports worktree creation by github PR URL
sudo apt install git xfsprogs gdisk
gh can be installed following these instructions.
Install stol to a location on your PATH:
make installThis builds and installs all executables to ~/.local/bin. You may override the install location with PREFIX.
make install PREFIX=/usr/localBe sure to follow the post-install instructions to finish setting up your environment.
With stol installed, provision the reflink-capable filesystem it will use for
$STOL_ROOT. By convention we mount it at /mnt/work, but any location works as
long as your user owns the mount point.
First create the mount point:
sudo mkdir /mnt/work
sudo chown $USER:$USER /mnt/workThen provision the filesystem with one of the helpers (see the two options above) and mount it there:
stol create-image: create and format a disk imagestol format-drive: format a dedicated physical disk
stol format-drive must run as root. Be careful to use the correct disk in
this command, or you may lose data.
sudo "$(command -v stol-format-drive)" /dev/disknamestol prescribes a particular directory layout under $STOL_ROOT.
$STOL_ROOT/projects/<repository name>/<worktree name>
Each time you stol import a new repository, you get a new directory under $STOL_ROOT for that repo. That new directory contains each of its worktrees as subdirectories.
Your projects directory will look something like this:
/mnt/work/projects $ tree -L 2 -a
.
├── my-project.git
│ ├── .repo
│ ├── .stol
│ ├── 00-main
│ ├── task-1
│ ├── task-2
│ └── task-3
└── stol.git
├── .repo
├── .stol
├── 00-main
└── feature-1
There are four kinds of directories under a project:
.repo: the main checkout of the repo. You should never have to think about this.00-{branchname}: a "template" worktree. Most of the time you will have exactly one, with the main branch checked out..stol: a place for your repo-specific hooks.- The remaining directories are worktrees created by
stol new.
When you import a project with stol import, it creates a .repo directory and
an initial "template" worktree.
When you create a new worktree with stol new, it makes a reflinked copy
of the template worktree. If you have multiple template worktrees,
stol new prompts you to select one.
In order to pick up the latest changes in your template worktree, you can run
stol sync <project>. It is also safe to run git pull yourself.
You can conveniently delete worktrees with stol rm. It takes several forms:
stol rm . # delete the current worktree
stol rm <worktree> # delete a worktree by name in this project
stol rm <project>/<worktree> # delete a worktree by name in any projectscd is an interactive shell function that makes it quick and easy to jump
into a worktree, even if the target worktree does not yet exist.
Installation:
# bash users
source /path/to/stol.git/src/stol.bash
# zsh users
source /path/to/stol.git/src/stol.zsh
# fish users
source /path/to/stol.git/src/stol.fishUsage:
scd # cd to the projects root
scd <project> # cd to a project directory
scd <project>/<worktree> # cd to a specific worktreescd can create new worktrees implicitly:
scd -n <name> [<project>] # create a new worktree (new branch)
scd -e <branch> [<project>] # check out an existing branch in a new worktree
scd <pr-url> # check out a GitHub PR branch in a new worktreeWith -n and -e, the project can be omitted if your working directory is
already in a project.
If the worktree already exists, -e and PR URLs will cd there without
recreating it.
The PR URL form is shorthand for -e. It resolves the branch name and project
from the URL via gh, so instead of:
scd -e someone/branch-name repo-nameyou can do:
scd https://github.com/Applied-Intuition-Open-Source/stol/pull/1You can add hooks to customize stol commands by placing executables in
.stol/hooks/ inside your project directory.
my-project/
├── .stol/
│ └── hooks/
│ ├── post-new
│ └── pre-remove
├── .repo/
└── 00-main/
- post-new: runs after the worktree is created, inside the new worktree directory.
- pre-remove: Runs inside the worktree directory, before it is deleted.
You can add new stol subcommands by placing an executable prefixed with stol-
in your PATH. stol my-subcmd will call stol-my-subcmd internally.