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 → collapses upward, restoring parent directories to symlinks

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.2.0.tar.gz (59.5 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.2.0-py3-none-any.whl (25.7 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for repoworktree-0.2.0.tar.gz
Algorithm Hash digest
SHA256 e45e97102b8ef06c607dbed9f3ccf6de4b8f6cadc412c97aae25d44bd36e4ac6
MD5 8b69c661d16a25e9df46f5c09fb262e7
BLAKE2b-256 3fc2371eb986b65b4f42760da6a06460dab2b0294c7730cfaea1eb800c6dd4ef

See more details on using hashes here.

Provenance

The following attestation bundles were made for repoworktree-0.2.0.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.2.0-py3-none-any.whl.

File metadata

  • Download URL: repoworktree-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 25.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.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3bc20bc69b385310d06590ccf0b6cc5c4b27d90a770489794275ea35d9aca8fd
MD5 d11fbf17d2a5b26e2bc3cdc183e98482
BLAKE2b-256 a6b8f0eb5dedd6a91f0d729e55e5f079d2cd17cbbee2d3bd8df392b7a52c87cc

See more details on using hashes here.

Provenance

The following attestation bundles were made for repoworktree-0.2.0-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