Workspaces wrap git worktree: each workspace is a separate directory on disk with its own checkout, but they all share a single Git object database. You keep multiple branches alive at once — no stashing, no second clone, no lost context.
When to use workspaces
| Situation | Without workspaces | With g workspace |
|---|---|---|
| Urgent hotfix arrives while you’re mid-feature | git stash, switch, fix, pop stash, pray | Open a second directory on main, fix there, come back |
| Two long-running tracks at once | Clone the repo a second time | One object store, two named directories |
| Review a teammate’s branch locally | Abandon your current state | Create a workspace for their branch, switch in seconds |
Work on a feature that needs .env tweaks | Manually copy files each time | --copy brings your untracked files along |
| Onboarding a fresh repo | git clone, settle for flat layout | git clone then g workspace init, container layout from day one |
Two directory layouts
Sibling layout (default)
Each workspace lives next to the repo root, joined by a configurable separator:
~/projects/myapp ← main repo (main branch)
~/projects/myapp--feature-auth ← workspace (feat/auth branch)
~/projects/myapp--hotfix ← workspace (fix/oauth branch)
Container layout
Enabled by g workspace init. The original repo path becomes a container directory; each workspace is a child:
~/projects/myapp/ ← container
~/projects/myapp/main/ ← primary workspace (main branch)
~/projects/myapp/feature-auth/ ← workspace (feat/auth branch)
~/projects/myapp/hotfix/ ← workspace (fix/oauth branch)
Once in container layout, every future g workspace create places new worktrees inside the container automatically — no configuration needed.
Use cases
Fix a production bug without touching your feature branch
Who: You are halfway through feat/notifications. A login bug just hit production. It needs a patch on main now.
Goal: Produce a fix commit and PR without abandoning or stashing your current work.
What to do
-
From anywhere in your repo, create a hotfix workspace branching off
main:g workspace create hotfix -b fix/oauth-tokengcreatesmyapp--hotfix(sibling) ormyapp/hotfix(container) and checks out a newfix/oauth-tokenbranch there. Your current directory is untouched. -
Switch into it:
g workspace switch hotfix # A subshell opens inside myapp--hotfix -
Fix, test, commit, push, open PR — exactly as normal:
# ... edit files ... g commit -m "fix(auth): refresh token expiry window" g push origin fix/oauth-token -
Exit the shell when you are done. Your feature branch is right where you left it:
exit # back in myapp on feat/notifications -
Once the hotfix is merged, clean up:
g workspace delete hotfix
Run two long-lived features in parallel
Who: You own both the search redesign and the billing refactor. Each takes weeks. Switching between them with git switch means rebuilding caches, restarting dev servers, and losing IDE state every time.
Goal: Keep both tracks alive on disk at the same time.
What to do
-
Set up both workspaces once:
g workspace create search-v2 --description "Elasticsearch rollout" g workspace create billing-ui -b feat/billing-shell --description "Stripe v3 migration" -
See what is running:
g workspace list◉ main main ~/projects/myapp/main abc1234 — ◯ search-v2 feat/search ~/projects/myapp/search-v2 def5678 3 hours ago ◯ billing-ui feat/billing ~/projects/myapp/billing-ui 9ab0123 1 day ago -
Jump between them as needed:
g workspace switch # interactive fuzzy picker — type to filter g workspace switch search-v2 # or directly by name -
Each workspace gets its own
node_modules, build cache, and editor window. Switching is opening a shell tab — not agit switch.
Pick up a teammate’s branch for local testing
Who: You are reviewing a PR for feat/new-dashboard. You want to run it locally without leaving your current branch.
Goal: Check out their branch in a separate directory while staying on your own work.
What to do
-
Their branch exists on
originbut not locally.gtracks it automatically:g workspace create dashboard-review -b feat/new-dashboard # → finds origin/feat/new-dashboard, creates a local tracking branch -
Switch in, run their dev server on a different port, test:
g workspace switch dashboard-review npm run dev -- --port 3001 -
Leave feedback, exit, delete:
exit g workspace delete dashboard-review
Start a new project with workspace layout from day one
Who: You are cloning a repo for a new engagement. You know you will work on multiple branches over time and want the container layout from the start.
Goal: Clone and be workspace-ready before writing a single line of code.
What to do
git clone https://github.com/org/api-service.git
cd api-service
g workspace init
cd ../api-service/main
What happened:
~/projects/api-service/ ← container created
~/projects/api-service/main/ ← repo moved here
From now on, g workspace create feature-x places the worktree at api-service/feature-x/.
Convert an existing repo to container layout
Who: You cloned the repo months ago the normal way. You have started hitting the “too many stashes” problem and want to switch to worktrees properly.
Goal: Reorganise the existing clone in place without losing any work.
What to do
-
Make sure your working tree is clean (commit or stash anything in progress):
g status -
Run
initfrom inside the repo:cd ~/projects/myapp g workspace initinitprints its plan — exactly which directories will move — and asks for confirmation before touching anything:move ~/projects/myapp → ~/projects/myapp--ws-tmp mkdir ~/projects/myapp move ~/projects/myapp--ws-tmp → ~/projects/myapp/main Proceed? [y/N] -
Confirm, then navigate to the new inner location:
cd ~/projects/myapp/main -
Create your first extra workspace:
g workspace create feature-x # → placed at ~/projects/myapp/feature-x/
Bring your local config files along
Who: Your project needs .env, config/local.yml, and a self-signed cert that are gitignored and live only in your checkout. You branch off to work on a new feature but those files are missing from the fresh worktree.
Goal: Copy just the files you need into the new workspace without manual cp commands.
What to do
g workspace create feature-payments --copy
An interactive checklist appears listing every untracked and gitignored file in your current workspace:
Select files to copy into the new workspace (space to toggle, enter to confirm)
> [x] .env
[ ] .env.test
[x] config/local.yml
[ ] certs/localhost.pem
Toggle with Space, confirm with Enter. Only the selected files are copied — directory structure is preserved.
Jump to any workspace from anywhere
Who: You have four workspaces open and lost track of which terminal is which.
Goal: Get into the right workspace without remembering the exact name.
What to do
Run switch with no argument:
g workspace switch
A fuzzy-searchable list opens:
Switch to workspace
> ◉ main main ~/projects/myapp/main
◯ feature-auth feat/auth ~/projects/myapp/feature-auth
◯ hotfix fix/oauth ~/projects/myapp/hotfix
◯ billing-ui feat/billing ~/projects/myapp/billing-ui
Type any part of the name, branch, or path to filter. The workspace you are currently inside is pre-selected. Press Enter to open a shell there, Escape to cancel.
Command reference
g workspace init
Reorganise an existing repo into container layout. Shows a plan and asks for confirmation. On failure, rolls back to the original state.
g workspace init
g workspace list
Show all worktrees with metadata. The ◉ marker indicates the workspace your shell is currently inside.
g workspace list
Name Branch Path HEAD Created
─ ──────────── ───────────── ────────────────────────────────── ─────── ───────
◉ main main ~/projects/myapp/main abc1234 —
◯ feature-auth feat/auth ~/projects/myapp/feature-auth def5678 2 days ago
◯ hotfix fix/oauth ~/projects/myapp/hotfix 9ab0123 4 hours ago
g workspace create
# New branch named after the workspace
g workspace create feature-auth
# New branch with a custom name
g workspace create hotfix -b fix/oauth-token
# New branch from a specific commit
g workspace create hotfix -b fix/oauth-token abc1234
# Existing local or remote branch (remote auto-tracked if not local)
g workspace create auth-review -b feat/auth
# With a description shown in list view
g workspace create search-v2 --description "Elasticsearch rollout"
# Copy untracked/gitignored files from the current workspace
g workspace create feature-payments --copy
# Combine flags
g workspace create feature-x -b feat/x --description "New feature" --copy
Branch resolution order:
- Exists locally → check out directly.
- Exists on
originonly → create a local tracking branch. - Neither → create a fresh branch (optionally from a start point).
g workspace switch
g workspace switch # interactive fuzzy picker
g workspace switch feature-auth # direct by name (fuzzy matched)
Opens a subshell in the workspace directory. Exit with exit or Ctrl+D to return.
g workspace status
Show what workspace you are currently inside, its branch, path, creation time, and a change summary.
g workspace status
Run this from any linked worktree — useful when you forget which checkout you are in.
g workspace rename
Rename a workspace — moves the directory on disk and runs git worktree repair to update git’s internal tracking.
g workspace rename feature-auth auth-v2
g workspace delete
g workspace delete auth-v2
g workspace delete auth-v2 --force # remove even with uncommitted changes
Remote branch auto-tracking
When you pass -b <branch> to create and that branch does not exist locally, g checks origin/<branch> before creating a fresh branch:
# origin/feat/payments exists locally
g workspace create payments -b feat/payments
# → git worktree add ... -b feat/payments --track origin/feat/payments
If neither local nor remote is found, a new branch is created from the current HEAD (or from start_point if given).
Configuration
[workspace]
separator = "--" # sibling layout only: myapp--workspace-name
The separator has no effect in container layout — workspace names become directory names directly.
Under the hood
g workspace is a thin layer on top of standard git worktree commands:
git worktree add <path> <branch> # existing local branch
git worktree add -b <branch> --track origin/<b> <path> # remote tracking branch
git worktree add -b <branch> <path> <start-point> # new branch from commit
git worktree list --porcelain # list (for display)
git worktree remove [--force] <path> # delete
git worktree repair # after rename or init
git ls-remote --symref <url> HEAD # clone: detect default branch
Metadata (friendly names, descriptions, creation timestamps, container root) is stored in ~/.config/g/workspaces.toml alongside the rest of your local developer state. It is not part of the repository and is not committed.
Tips
g workspace statustells you which checkout you are in from any linked worktree — useful when you have three terminals open on the same repo.g workspace switch(no argument) is faster thanlistfor navigating: just type a fragment of the name or branch.- One workspace per long-running branch beats stashing. Stashes accumulate; workspaces have names.
- Preview destructive operations with
g --dry-run workspace initto see exactly what will move before it moves. - See Git flows for how worktrees complement stack workflows — for example, fixing
mainin a hotfix workspace while a feature stack stays open in another directory.