gitto

gitto copies a whole working directory with the filesystem's own clone call: history, submodules, dependencies and build output, then re-addresses what the copy would break. Nothing is duplicated until one side writes.

A second checkout of the repository you are working in, whatever it weighs.

Why it exists

Open a second branch and you open a second checkout. git worktree add makes one in a moment, and hands you the files git tracks. Everything else you were working with stays behind: installed dependencies, compiled artifacts, initialised submodules, the local configuration you never commit.

So each checkout begins with the install and the build you already ran. Three of them at once, which is what running several agents means, and you have paid for the same build three times before any of them starts.

Filesystems have been able to avoid this for years. APFS, btrfs, XFS and OpenZFS all copy a file by pointing at the same blocks and splitting them only when one side writes, so a copy of a 13 GB checkout costs the time to walk its directory entries and almost no space. gitto copies the directory that way and repairs what a copy would otherwise break.

What it is

One POSIX shell script. It copies the canonical checkout with the filesystem's own clone call, puts the copy on a new branch, and re-addresses the references that would still point at the original.

A copy of a checkout is not immediately a working checkout, because a checkout is full of paths to where it lives: core.hooksPath, worktree registrations at every submodule depth, symlinks into the directory it came from. gitto repairs those it can, drops what cannot survive the move, and reports the rest.

Measured on a 13 GB checkout with four submodules: 21 seconds, 60 MB of real disk.

What it is not

It does not replace git clone, which is how a repository reaches a machine for the first time. It does not sync, watch or merge anything. It never writes to the canonical checkout, and it never reaches the network except through the git fetch that new runs before it picks a base.

Setting up the shell

A command cannot change the directory of the shell that started it. Add the function once and gitto new takes you to what it made:

eval "$(gitto shell-init)"

Where to go next

Read Concepts for the four words the refusals are written in, Commands for what each one takes, and Caveats before you trust doctor with a deletion.

On this page