git-cow 0.1.0

Git worktrees that share files with a template through copy-on-write clones (APFS, XFS, btrfs)
Documentation

git-cow

git worktree add that clones files instead of copying them. Every new worktree is a copy-on-write clone of a template checkout, so target/, node_modules and other build output are shared on disk until a build rewrites them. A worktree that would cost gigabytes starts at a few megabytes and builds incrementally.

cargo install git-cow
git cow add -b feat/login                 # ~/.worktrees/<repo>/login
git cow add -b feat/login ../login        # any path, like git worktree add
git cow warm ~/.worktrees/<repo>/login    # after a merge, share its build output with the next worktree

A binary named git-cow on your PATH is a git subcommand, so git cow works once it is installed.

How it works

  1. Keep one template checkout per repository at <worktree's parent>/.git-cow/<repo>, moved to origin/HEAD before each clone.
  2. Clone the gitignored directories of your checkout into the template: build output and dependencies, never loose ignored files like .env and never paths with a hidden component.
  3. git worktree add --no-checkout, then clone every template entry except .git into it. macOS uses cp -c (clonefile), Linux cp --reflink=always (FICLONE).
  4. Copy the template's index, refresh it, and git reset --hard, which rewrites only the files where your branch differs from the template.

If the volume cannot clone, or anything fails, it removes what it made and runs plain git worktree add with the same arguments.

Configuration

Default
git config cow.root ~/.worktrees Where a worktree goes when the path is left out: <root>/<repo>/<last part of the branch>
git config cow.template <worktree's parent>/.git-cow/<repo> The template checkout
GIT_COW=0 Plain git worktree add

The checkout, the template and the worktrees must be on one volume that clones: APFS on macOS, XFS formatted with reflink=1 or btrfs on Linux. ext4 and HFS+ always fall back.

Library

git_cow::add(repo, template, "origin/main", worktree, Some("feat/x"), None)?;
git_cow::warm(merged_worktree, template)?;

Synchronous and without dependencies. A lock file next to the template keeps concurrent clones, from threads or processes, from seeing it half updated.

Costs

  • A cloned file's blocks are copied the first time either side writes it.
  • git update-index --refresh re-hashes every tracked file, since clones have new inodes. That grows with the number of tracked files.
  • Output that embeds absolute paths, such as virtualenvs, points at the template. Whether the tool recovers is up to the tool.
  • A directory where everything is ignored is shared whole, hidden subdirectories included, because git reports it as one entry.
  • The template is one more checkout on disk and shows in git worktree list.
  • Repositories with submodules always fall back.

Origin

Extracted from orch, where every agent task gets a worktree. Measured there on APFS: a warmed clone built in 55 to 72 s against 73 s for a plain worktree, and wrote about 1 GB less per task.

MIT licensed.