Skip to main content

Isolated workspaces for repo-managed multi-repository projects using git worktree + symlink

Project description

repoworktree

PyPI Python

Create isolated workspaces for Google repo-managed multi-repository projects using git worktree + symlink. Supports a continuous spectrum from all-symlink (zero overhead, read-only) to all-worktree (fully isolated).

中文文档

All symlink (read-only)                              All worktree (fully isolated)
│  rwt create /tmp/ws              rwt create /tmp/ws --all  │
│         ◄── rwt promote / demote dynamically ──►           │
└────────────────────────────────────────────────────────────┘

Install

Python 3.10+, no third-party dependencies.

pip install repoworktree

Quick Start

# Create workspace, specify repos to modify
rwt create /tmp/ws-agent1 -w nuttx,apps -n "fix-serial-driver"

# Develop in the workspace
cd /tmp/ws-agent1
source envsetup.sh && lunch && m   # build works normally

# Need to modify more repos during development
rwt promote frameworks/system/core

# Done with a repo, demote back to symlink
rwt demote frameworks/system/core

# Destroy workspace
rwt destroy /tmp/ws-agent1

Command Reference

rwt create — Create workspace

rwt create <path> [options]
Option Description
<path> Workspace target path
-n, --name Workspace name (default: directory name)
-w, --worktree Comma-separated sub-repo paths to create as git worktrees
--all Create git worktrees for all sub-repos
-s, --source Main repo checkout path (default: auto-detect .repo/)
--checkout Check out this branch or tag for all worktrees (default: source HEAD)
--pin Pin version, format repo=version[,repo=version,...]
-b, --branch Create named branch instead of detached HEAD

Examples:

# All symlink read-only (extreme A)
rwt create /tmp/ws-readonly

# Typical: modify a few repos
rwt create /tmp/ws-agent1 -w nuttx,apps -n "fix-serial-driver"

# Modify nested sub-repo
rwt create /tmp/ws-bt -w nuttx,apps/system/adb

# Parent and child repos both writable
rwt create /tmp/ws-dev -w apps,apps/system/adb

# All worktree fully isolated (extreme B)
rwt create /tmp/ws-full --all

# Pin version + named branch
rwt create /tmp/ws-stable -w nuttx --pin nuttx=v12.0.0 -b feature/new-driver

# Check out a specific branch/tag for all worktrees (without pinning — sync still works)
rwt create /tmp/ws-release --all --checkout release/v2.0

rwt destroy — Destroy workspace

rwt destroy <path|name> [-s source] [-f]
Option Description
<path|name> Workspace path or name
-s, --source Source repo checkout path (for name lookup, default: auto-detect)
-f, --force Force destroy even with uncommitted changes or local commits
rwt destroy /tmp/ws-agent1
rwt destroy fix-serial-driver     # by name
rwt destroy /tmp/ws-dirty -f      # discard uncommitted changes

rwt promote — Promote sub-repo to writable worktree

Run inside a workspace to dynamically promote a symlinked sub-repo to a git worktree.

rwt promote <repo_path> [options]
Option Description
<repo_path> Sub-repo path (e.g. nuttx, frameworks/system/core)
--pin Checkout specific version
-b, --branch Create named branch
cd /tmp/ws-agent1
rwt promote vendor/xiaomi/miwear
rwt promote frameworks/system/core --pin abc1234
rwt promote nuttx -b fix/uart-bug

Promote handles nesting automatically:

  • Top-level symlink → directly replaced with worktree
  • Deep nested (e.g. frameworks/system/core) → parent symlinks split into real dir + symlink mix
  • Parent repo already has child worktrees → temporarily removes children, creates parent worktree, restores children

rwt demote — Demote worktree to read-only symlink

rwt demote <repo_path> [-f]
Option Description
<repo_path> Sub-repo path
-f, --force Force demote, discard uncommitted changes
rwt demote apps
rwt demote apps -f    # discard changes

Demote handles nesting automatically:

  • With child worktrees → preserves children, rebuilds parent as real dir + symlink structure
  • Without child worktrees → the repo itself becomes a symlink; parent directories remain as real dirs

rwt list — List all workspaces

rwt list [-s <source>] [--json]

rwt status — Show workspace details

rwt status [<path|name>] [-s source] [--json]

rwt sync — Sync workspace

rwt sync [-W workspace] [--rebase]

After repo sync on the main checkout, symlinks follow automatically. Worktrees need manual sync:

Worktree state Default --rebase
symlink auto follows same
worktree, pinned skip skip
worktree, uncommitted changes skip, report skip, report
worktree, local commits skip, report rebase onto latest
worktree, clean update to source HEAD same

rwt pin / rwt unpin — Version pinning

rwt pin <repo_path> [<version>]
rwt unpin <repo_path>

rwt export — Export changes

rwt export [--format patch|bundle] [-o <dir>]

Use Cases

Parallel multi-agent development

# Two agents modify nuttx simultaneously, fully isolated
rwt create /tmp/ws-agent1 -w nuttx -n "agent1-serial-fix"
rwt create /tmp/ws-agent2 -w nuttx -n "agent2-spi-driver"

Dynamic adjustment during development

# Start with only nuttx
rwt create /tmp/ws-dev -w nuttx

cd /tmp/ws-dev

# Need to modify apps/system/adb
rwt promote apps/system/adb

# Also need to modify apps itself
rwt promote apps

# Done with apps, demote back
rwt demote apps

Push changes to Gerrit

cd /tmp/ws-agent1/nuttx
git push origin HEAD:refs/for/main

Workspace Structure

/tmp/ws-agent1/
├── .workspace.json     # workspace metadata
├── nuttx/              # git worktree (writable)
├── apps/               # real directory (has worktree descendants)
│   ├── system/
│   │   ├── adb/        # git worktree (writable)
│   │   └── core/       # symlink → source (read-only)
│   └── benchmarks/     # symlink → source (read-only)
├── build/              # symlink → source (read-only)
├── frameworks/         # symlink → source (read-only)
├── build.sh            # symlink (preserves original relative link)
└── CLAUDE.md           # symlink → source

How It Works

  • Symlinked repos: Zero overhead, point directly to the main checkout directory. Read-only — modifications affect the main checkout.
  • Worktree repos: Created via git worktree add with their own HEAD, index, and working tree. Fully isolated.
  • Nested repos: repo-managed projects have parent-child repos (e.g. apps/ and apps/system/adb/ are independent git repos). When a child needs a worktree, parent symlinks are split into real directories with symlinked siblings — real directories are only created along the path to the worktree.
  • Metadata: .workspace.json stores per-workspace config. .workspaces.json in the source root indexes all workspaces.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

repoworktree-0.3.1.tar.gz (72.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

repoworktree-0.3.1-py3-none-any.whl (28.7 kB view details)

Uploaded Python 3

File details

Details for the file repoworktree-0.3.1.tar.gz.

File metadata

  • Download URL: repoworktree-0.3.1.tar.gz
  • Upload date:
  • Size: 72.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for repoworktree-0.3.1.tar.gz
Algorithm Hash digest
SHA256 a1a8ee7264c5146e1aa19ca2bf2df8b7019df29d3a84929065ac36c7e5c4550b
MD5 838378e35d4c6e781f64285f38a30d24
BLAKE2b-256 3f34cd6484a051f1fefdd6f4960ffa20ac540c0a955f0852c0daaa622de1326e

See more details on using hashes here.

Provenance

The following attestation bundles were made for repoworktree-0.3.1.tar.gz:

Publisher: publish.yml on XuNeo/repoworktree

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file repoworktree-0.3.1-py3-none-any.whl.

File metadata

  • Download URL: repoworktree-0.3.1-py3-none-any.whl
  • Upload date:
  • Size: 28.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for repoworktree-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 27b1ec10bf770edcee21e9a6bb982a7cd0ff5596a30b344716d5e883224bd1ee
MD5 205c4187d24e64c71cf55becb6a06cbc
BLAKE2b-256 9ff4d3ff83dd8d923d167d4994d7016e63fe9d110b3137c94b559b103e89561c

See more details on using hashes here.

Provenance

The following attestation bundles were made for repoworktree-0.3.1-py3-none-any.whl:

Publisher: publish.yml on XuNeo/repoworktree

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page