Git worktree workspace manager. Creates multi-repo workspaces using git worktrees instead of symlinks.
When you symlink repos into a workspace directory, tools that resolve paths (IDEs, sandboxes, Claude Code) see the real paths outside your workspace and prompt for permissions or lose context. Worktrees create real directories inside the workspace — same files, shared git object store, no path resolution issues.
brew install cemcatik/tap/git-rigcurl --proto '=https' --tlsv1.2 -LsSf https://github.com/cemcatik/git-rig/releases/latest/download/git-rig-installer.sh | shpowershell -ExecutionPolicy Bypass -c "irm https://github.com/cemcatik/git-rig/releases/latest/download/git-rig-installer.ps1 | iex"cargo install --git https://github.com/cemcatik/git-rigPre-built binaries are available on the releases page.
cargo install --path .The installed binary git-rig is also available as git rig (git auto-discovers git-* binaries on your PATH).
From the directory where your repos live:
cd ~/projects
git rig create my-featuregit rig add takes a path to a locally cloned repo (relative or absolute):
cd ~/projects/my-feature
git rig add ../api-server # new branch rig/my-feature from default
git rig add ../web-app --branch feature/PROJ-123 # specific branch
git rig add ~/projects/infra/auth-service --remote upstream # repo from a different directory
git rig add ../api-server --detach # read-only, detached HEAD
git rig add ../api-server --name api # custom name in rig
git rig add ../api-server --upstream develop # start from and sync against developWhen outside a workspace, pass the workspace name first:
git rig add my-feature ../api-serverTo change or clear the upstream for an existing repo, re-run add:
git rig add ../api-server --upstream integration # change upstream
git rig add ../api-server --no-upstream # revert to default branchTo create a new workspace with the same repos as an existing one:
git rig create my-feature-v2 --from my-featureEach repo gets a fresh rig/my-feature-v2 branch. Upstream and remote config are inherited. Local files from .riginclude are carried over from the source rig's worktrees. Use --skip to continue past repos whose source paths are no longer valid.
Repos often have local files (.env, IDE config, tool overrides) that are gitignored but needed for development. Create a .riginclude file in the repo root with gitignore-style patterns:
# .riginclude
.env*
.vscode/
docker-compose.override.yml
When git rig add or git rig create --from creates a worktree, matching files are automatically copied from the source:
git rig add ../api-server # copies .env, .vscode/, etc. from the clone
git rig create v2 --from v1 # copies from source rig's worktrees
git rig add ../api-server --no-provision # skip file provisioning
git rig add ../api-server --link # symlink instead of copy
git rig add ../api-server --force-provision # overwrite existing files.riginclude itself is always copied to the new worktree so it propagates automatically. The file can be gitignored (personal) or committed (team-shared).
Provisioning failures are warnings — the worktree is still created and usable.
git rig statusWorkspace: my-feature (/Users/you/projects/my-feature)
api-server on rig/my-feature [dirty] +2 -5 (vs develop)
last: a1b2c3d fix auth token refresh (2 hours ago)
web-app on feature/PROJ-123
last: d4e5f6a add tenant validation (3 days ago)
Repos with a custom --upstream show (vs <branch>) to indicate what they sync against.
If the filesystem/git state has diverged from the manifest (e.g., someone ran git checkout main inside a worktree), drift warnings appear at the top:
DRIFT api-server: on main, expected rig/my-feature
Drift detection runs automatically on status, sync, exec, and refresh. No flags needed.
git rig sync # all repos in current workspace
git rig sync --stash # auto-stash dirty repos before rebasing
git rig sync --repo api-server # sync only specific repo(s)
git rig sync --repo api-server --repo web # sync multipleSyncing workspace 'my-feature'
ok api-server 702a039 -> 069c37c
ok web-app already up to date
SKIP auth-service (dirty — use --stash to auto-stash)
ok All repos synced
Repos with drift (branch mismatch, unexpected detached HEAD, missing source) are automatically skipped during sync to prevent rebasing the wrong branch.
git rig exec -- git status # run in all repos
git rig exec --repo api-server -- make # run in specific repo(s)
git rig exec --fail-fast -- cargo test # stop on first failure
git rig exec -w my-feature -- git pull # target a workspace by nameIf upstream repos change their default branch (e.g. master → main), refresh the manifest:
git rig refreshgit rig remove api-server
git rig remove api-server --force # remove even if worktree is dirty
git rig remove api-server --keep-branch # keep the branch in the source repo (default: deleted)git rig listgit rig destroy my-feature
git rig destroy my-feature --dry-run # preview what would be removed
git rig destroy my-feature --keep-branches # keep branches in source reposThis removes all worktrees, deletes their branches, and removes the workspace directory. Force-removes dirty worktrees.
Each workspace is a directory containing a .rig.json manifest:
{
"name": "my-feature",
"repos": [
{
"name": "api-server",
"source": "/Users/you/projects/api-server",
"branch": "rig/my-feature",
"default_branch": "master",
"remote": "origin",
"upstream": "develop"
}
]
}- Each repo entry stores the absolute
sourcepath to the local git clone upstreamis optional — when set, the worktree starts from this branch andsyncrebases onto it instead ofdefault_branch- Repos can live anywhere on disk — they don't need to be siblings of the workspace
- Worktrees are created inside the workspace directory
- Commands that accept an optional workspace name (
add,remove,status,sync,refresh,exec,doctor) auto-detect the workspace by walking up from CWD
Requires just for task running:
just check # fmt + clippy + test (recommended before committing)
just test # all tests
just test-unit # unit tests — manifest ops, workspace resolution
just test-integration # integration tests — git operations against real repos
just test-e2e # E2E tests — full CLI commands via assert_cmd
just cross-check # verify all release targets compile (no linker needed)
just coverage # generate lcov coverage report
just deny # license + advisory audit (requires cargo-deny)just cross-check runs cargo check against all five release targets (macOS arm64/x86, Linux arm64/x86, Windows x86). This catches platform-specific compilation errors (like using std::os::unix without #[cfg] guards) without needing cross-compilers or linkers. Missing targets are installed automatically via rustup.
A pre-commit hook (hooks/pre-commit) is auto-installed into .git/hooks/ on the first cargo build or cargo test. It runs cargo fmt --check and cargo clippy before each commit. To update the hook after changes to hooks/pre-commit, delete .git/hooks/pre-commit and rebuild.
Tests create temporary git repos (bare remote + clone) per test case — no shared state, no CWD mutation.
scripts/release.sh 0.2.0This bumps the version in Cargo.toml, updates Cargo.lock, commits, tags, and pushes. The tag push triggers the release workflow which builds binaries, creates a GitHub Release, and publishes the Homebrew formula.
git rig doctorEnvironment
PASS git found on PATH
PASS git version 2.39.0 (>= 2.30 required)
Rig: my-feature (2 repos)
api-server
PASS source repo exists
PASS worktree exists and reachable
PASS branch matches manifest (rig/my-feature)
PASS origin/HEAD set
PASS remote 'origin' reachable
PASS upstream branch 'develop' exists on remote
web-app
PASS source repo exists
PASS worktree exists and reachable
WARN origin/HEAD not set
Default branch detection won't work.
Fix: cd /Users/you/projects/web-app && git remote set-head origin --auto
ok All checks passed
Checks environment prerequisites (git version >= 2.30) and per-repo health (worktree integrity, branch state, remote reachability, upstream validity). Works outside a rig too — shows environment checks only. Exits 1 on any issue for scripting/CI use.
git rig completions bash > ~/.bash_completion.d/git-rig
git rig completions zsh > ~/.zfunc/_git-rig
git rig completions fish > ~/.config/fish/completions/git-rig.fish
git rig completions powershell > _git-rig.ps1- A git branch can only be checked out in one worktree at a time. If
git rig addfails with "already checked out", the error tells you which worktree has the branch. - Default branch detection requires
origin/HEAD(or<remote>/HEAD) to be set. For repos not created viagit clone, run:git remote set-head origin --auto git rig destroyforce-removes worktrees.git rig removedoes not — it fails on dirty worktrees unless--forceis passed.--upstreamsets the branch that the worktree starts from and thatsyncrebases onto. The upstream branch must exist on the remote at add time. Git tracking andgit logwill reference the upstream ref..rigincludeuses gitignore pattern syntax (globs,**, trailing/for directories,!for negation,#for comments). Only the file at the repo root is read — no recursive/nested.rigincludefiles.- You can edit
.rig.jsondirectly to change remotes, branches, or other settings. - If you manually switch branches inside a worktree (
git checkout main),statusandsyncwill detect the mismatch and warn.syncwill skip the drifted repo to prevent rebasing the wrong branch.