Compare to git
Git's verbs keep git's names. Here is each common git command next to the quilt command that does its job, and then what works differently.
Commands side by side
| git | quilt | Notes |
|---|---|---|
git init | quilt quilts new <slug> | main starts at an empty root commit. |
git clone | quilt checkout <rev> --quilt <q> --dir <folder> [-- paths] | Writes files only, no history. Name paths for a sparse checkout. |
git switch -c <branch> | quilt square open "<title>" --quilt <q> [--dir <folder>] | A square starts at the tip of main. |
git switch <branch> | quilt checkout sq:<id> | Inside a block folder with nothing uncommitted. |
git branch | quilt square list [--mine] [--all] | Open squares, or every square with --all. |
git status | quilt status | In a block folder. Also says what merged under you. |
git add + git commit | quilt commit -m "<message>" [paths] | No staging area. |
git push | (nothing) | A commit is on the server when it is made. |
git pull --rebase | quilt rebase | Moves the square onto the tip and updates the folder. |
git diff | quilt diff | Your uncommitted changes, in a block folder. |
git diff a b | quilt diff a b, quilt diff a..b | Also --stat and --name-only. |
git log | quilt log [rev] [-n 20] [--oneline] [-- paths] | Newest first. Ranges like main~5..main work. |
git show | quilt show <rev> [--stat | --name-only] | |
git blame | quilt blame <path>[@rev] | Computed by the server, with the patch of each line. |
git show rev:path | quilt cat <path>@<rev> | Writes the file's bytes to stdout. |
git ls-tree -r | quilt ls [rev] [paths] | |
git merge + push to main | quilt merge [sq:<id>] --into main | Rebased onto the tip as one patch, on the server. |
git merge <other> | quilt merge sq:<other> | In your block: a two-parent commit in your square. |
git rebase [--onto] | quilt rebase [--onto <rev>] | Conflicts are kept in the square; it never stops halfway. |
git cherry-pick | quilt cherry-pick <rev> | Into your square, as a new commit. |
git revert | quilt revert patch:<n> | Opens a new square that undoes the patch; merge it. |
git checkout --ours | quilt resolve <path> --ours | Also --theirs, --base, --suggestion, --side n, --delete. |
git branch -D | quilt square abandon | Kept and readable; quilt square reopen brings it back. |
git merge --squash a b | quilt square fold --into sq:<id> | One square's work becomes one commit in another. |
git add -p into two branches | quilt square split <paths,...> <paths,...> | Each group of paths moves to a new square. |
git fast-import | quilt import git <path> | Once, into a new quilt. |
git fast-export | quilt export git <dir> | One way, to a branch of a plain git repo. |
Inside a block folder the quilt and the square come from the folder. Anywhere else, name them with --quilt <slug> and --square sq:<id>.
What is different
No local history
A git clone carries every commit. A block folder carries only files, plus .quilt/block.json saying which quilt, square and commit they came from. log, show, blame and diffs between revisions are answered by the server. That keeps a checkout small and never stale, and it means you need to be online.
The server merges
Merging into main is one call. The server replays your square onto the current tip, combines changes to different parts of the same file, writes one commit and moves main with a compare-and-swap. If another merge won the race, it retries by itself, up to five attempts in all; after three lost races the merge waits its turn for the line, so it does land. There is no merge queue and nothing to pull first.
Because each square lands as one commit, main is a straight line of patches. Two-parent commits only happen inside squares.
Squares instead of branches
A square is not a name pointing at a commit. It is a record with an id, a title, a state and a holder: the one member who may commit to it. You hand it to someone else with quilt square handoff. Abandoning a square does not delete its commits; they stay readable by id.
Patch numbers
Each merge into main gets the next number. patch:412 always names the same change, and main~3 is three patches back. quilt log --oneline shows the number beside each commit: [main:412].
Conflicts are data
Git stops a merge with conflicts and waits for --continue or --abort. Quilt never stops halfway. A clash is stored in the commit as a conflict: each side, its base, and who made each side. The square carries it and keeps working; you can commit, rebase and hand it off. Only merging into main waits until it is settled. Read a conflicted file in the form you like: quilt cat <path>@sq:<id> --format diff (the default), snapshot or git (classic <<<<<<< markers, two sides only).
Authors are members
There is no --author. Each commit records the signed-in member, with the AI tool it came through (Author: builder <agent:5c1e…> via claude) and, for an agent, the person it works for.
What git has that Quilt Source does not
Some of these are left out on purpose. Others are in the design and not built yet.
Left out
- Push, pull, fetch and remotes. There is one server and it has every commit when it is made.
- The staging area and stash. Commit names paths when you want only some files; uncommitted work stays in its folder.
- Merge commits on main. Every square merges as one rebased patch.
- Hand-written authors and dates. The server records who you are and when.
Import and export
Import
$ quilt import git ./my-app [--into <slug>] [--validate]- Reads the repo on your computer and makes a new quilt. Each commit on
HEAD's first-parent chain becomes a patch onmain. - The side commits of a merge become the commits of that patch's square. A square from a merge commit like
Merge pull request #12 from ada/fixtakes the branch name as its title. - Authors become stub members,
stub:<email>, so blame and log keep their names. - Each imported commit remembers its git sha:
quilt show git:4d5bb0ffinds it. --validatecompares every patch's files with its git commit when the import is done.- Only
HEAD's history is imported. Other branches, tags and submodules are not.
Export
$ quilt export git ../my-app-git --quilt my-app [--line main] [--branch <name>]- Writes each patch of the line as one commit on a branch (named after the line unless you pass
--branch). A folder that does not exist yet becomes a new bare repo. - Run it again to add the patches merged since. It keeps its place in
quilt-export.jsoninside the git directory. - The same patch always gives the same git commit id, on any machine.
- Each commit message ends with trailers:
Quilt-Commit,Quilt-Square,Quilt-PatchandQuilt-Author, plusQuilt-On-Behalf-OfandQuilt-Taskwhen they apply. - Authors keep the email from a git import; everyone else gets a noreply address such as
<name>@agents.noreply.heyquilt.com. - It is one way. If the branch moved since the last export, the export refuses and asks for a new branch or repo. It never merges or forces.
Ready to try it? Get started walks through an import from the beginning.