English | 中文
git-workspace is a multi-repository workspace manager for git. You declare all your repositories in one YAML file, and one command assembles them into a real project tree — built from real git worktrees, no symlinks. Open the root in your IDE and develop, build, and debug as usual.
- 📄 One declarative config —
git-workspace.yamldescribes every repo: URL, revision, where to place it - 🌲 A real directory tree — assembled from git worktrees; IDE, pnpm, maven, and docker all see real paths
- 🔍 Sparse checkouts —
include/excludefilters fetch only what you need - 🔒 Read-only dependencies — third-party code is locked on disk; only
synccan write it - 📌 Reproducible — a lock file pins exact commit SHAs;
sync --lockedreproduces them exactly (CI-friendly) - 🛡 Commit protection — a pre-commit hook stops third-party code leaking into your repo by accident
- 🚀 Self-updating —
git-workspace updateupgrades the CLI to the latest release
Requires Python 3.8+, git, and PyYAML (the installers check/install PyYAML for you). Standalone installs always pin the latest release tag, never the development branch.
Linux / macOS / Git Bash:
curl -fsSL https://raw.githubusercontent.com/codingapi/git-workspace/main/install.sh | shWindows (PowerShell):
iex "& { $(irm https://raw.githubusercontent.com/codingapi/git-workspace/main/install.ps1) }"From a clone: ./install.sh (--prefix DIR overrides the default ~/.local).
mkdir my-project && cd my-project && git init
git-workspace init # creates git-workspace.yaml + commit-protection hooks
# edit git-workspace.yaml and declare your repositories
git-workspace sync # fetches everything and assembles the treeA minimal configuration:
version: 1
sources:
my-backend:
url: git@github.com:example/my-backend.git
revision: main
path: my-backend # assembly location (may nest, e.g. my-backend/web)
my-lib:
url: git@github.com:example/my-lib.git
revision: v1.0.0
path: libs/my-lib
include: [core] # check out only core/
readonly: true # lock it on diskThen work directly inside the assembled tree. Any directory you haven't
declared (e.g. app/) is tracked by your outer git repo as usual — no manual
.gitignore configuration needed.
This repository ships a runnable demo: cp example.yaml git-workspace.yaml && git-workspace sync assembles a backend repo, a nested frontend repo, and two
filtered read-only checkouts of the same third-party library.
Linux / macOS / Git Bash:
curl -fsSL https://raw.githubusercontent.com/codingapi/git-workspace/main/install.sh | sh -s -- --uninstallWindows (PowerShell):
iex "& { $(irm https://raw.githubusercontent.com/codingapi/git-workspace/main/install.ps1) } -Uninstall"Installed from a clone? Re-run ./install.sh --uninstall.
To also remove a workspace's worktrees and caches first: git-workspace clean --all.
| Command | Description |
|---|---|
git-workspace init |
Create a starter config + commit-protection hooks in the current directory |
git-workspace sync |
Fetch sources, materialize worktrees, refresh the lock |
git-workspace sync --locked |
Reproduce the exact locked SHAs; config must match the lock; lock is not rewritten (CI) |
git-workspace status |
Per-source SHA, dirty state, checkout filters, read-only state |
git-workspace outdated |
Check lock drift and newer upstream tags |
git-workspace verify |
CI gate: fail unless the lock exists and the tree matches it with every source clean (read-only sources also locked) |
git-workspace update |
Self-update to the latest release |
git-workspace clean [--all] |
Remove worktrees (--all also clears the object caches) |
git-workspace version |
Print the version (also -V / --version) |
git-workspace guard runs inside the pre-commit hook; you rarely call it
yourself. A Makefile wraps the common commands (make sync, make status,
make install, …).
git-workspace.yaml ──▶ engine ──▶ .workspace/git-cache/ (mirror clones, shared per URL)
│ │
▼ ▼
git-workspace.lock.yaml real worktree at each source path
+ managed git filters & pre-commit hook
- The engine —
git-workspaceitself: a single-file Python CLI (~850 lines) that depends only on git and PyYAML. It parses the config, orders the work, and delegates every heavy operation to native git (mirror clone, worktree, sparse-checkout, revision resolution). - Two repo roles — development repos are checked out in full and stay
editable where your product lives; consumed dependencies get checkout
filters plus a filesystem-level read-only lock, and the tool is their only
writer —
syncrefuses to run against a modified read-only source andverifyflags one. The lock is an anti-accident guardrail (POSIX permission bits; the read-only file attribute on Windows), not a security boundary — for tamper-proof CI inputs use a read-only mount and read-only credentials. - Mirror cache — bare clones under
.workspace/git-cache/, keyed by URL, so multiple sources from the same repository share one object store and are never downloaded twice. - Lock file —
syncresolves each revision to a SHA and writesgit-workspace.lock.yaml. Commit it, and anyone (or CI) reproduces the exact tree withsync --locked: in that mode the engine checks out the locked SHA verbatim (a floating revision likemainadvancing upstream is ignored), requires the config's source set,urlandrevisionto match the lock, and never rewrites it.verifyis the CI gate for this: it fails unless the lock exists and is well-formed, config and lock agree, and every source is materialized at its locked SHA with a clean worktree (read-only sources must also be filesystem-locked). - Workspace root discovery — the CLI walks up from the current directory
to find
git-workspace.yaml, so it behaves identically whether installed globally or run from a clone. - Managed git filters — every sync rewrites marked blocks in the repos' exclude files (self-healing): assembly paths are ignored by the outer repo, and everything undeclared is tracked as usual.
- Safety — sync refuses to overwrite uncommitted work or local commits;
the
guardhook blocks force-adding assembly directories or embedded git repositories into the outer repo. - Release channel — installers pin the latest release tag, and
git-workspace updatecompares your version against it and upgrades in place.
Development needs nothing but Python 3, PyYAML, and git — run the CLI straight from the clone:
git clone git@github.com:codingapi/git-workspace.git && cd git-workspace
./git-workspace -h
# end-to-end smoke test against the bundled example:
cp example.yaml git-workspace.yaml && ./git-workspace sync && ./git-workspace status && ./git-workspace verify
./git-workspace clean --all && rm git-workspace.yaml git-workspace.lock.yamlGuidelines:
- Keep the single-file design — the entire engine is
git-workspace; no build step, stdlib + PyYAML only. - Keep it declarative — new capabilities belong in
git-workspace.yaml, not in flags. - Run the regression suite before sending a PR:
python -m unittest discover -s tests -v(needs git + PyYAML). CI runs it on Linux, macOS and Windows via.github/workflows/ci.yml. - Releases: bump
__version__→ commit →git tag v<version>→ push the tag; installers andupdatepick it up automatically.
Note: since v0.4.0 the mirror-cache directory name includes a short hash of the source URL (so distinct URLs can never share a cache). Upgrading re-clones each source once; the old cache directories are left behind and can be removed with
git-workspace clean --all.
Issues and pull requests: https://github.com/codingapi/git-workspace