https://github.com/codingapi/git-workspace
https://github.com/codingapi/git-workspace
Last synced: 7 days ago
JSON representation
- Host: GitHub
- URL: https://github.com/codingapi/git-workspace
- Owner: codingapi
- License: apache-2.0
- Created: 2026-07-30T07:36:33.000Z (9 days ago)
- Default Branch: main
- Last Pushed: 2026-07-30T11:00:51.000Z (9 days ago)
- Last Synced: 2026-07-30T11:10:11.683Z (9 days ago)
- Language: Python
- Size: 77.1 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# git-workspace
**English** | [δΈζ](README.zh-CN.md)
[](https://github.com/codingapi/git-workspace/actions/workflows/ci.yml)
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.
## Features
- π **One declarative config** β `git-workspace.yaml` describes 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`/`exclude` filters fetch only what you need
- π **Read-only dependencies** β third-party code is locked on disk; only `sync` can write it
- π **Reproducible** β a lock file pins exact commit SHAs; `sync --locked` reproduces them exactly (CI-friendly)
- π‘ **Commit protection** β a pre-commit hook stops third-party code leaking into your repo by accident
- π **Self-updating** β `git-workspace update` upgrades the CLI to the latest release
## How to use
### Install
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:**
```bash
curl -fsSL https://raw.githubusercontent.com/codingapi/git-workspace/main/install.sh | sh
```
**Windows (PowerShell):**
```powershell
iex "& { $(irm https://raw.githubusercontent.com/codingapi/git-workspace/main/install.ps1) }"
```
From a clone: `./install.sh` (`--prefix DIR` overrides the default `~/.local`).
### Set up a workspace
```bash
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 tree
```
A minimal configuration:
```yaml
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 disk
```
Then 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.
## Uninstall
**Linux / macOS / Git Bash:**
```bash
curl -fsSL https://raw.githubusercontent.com/codingapi/git-workspace/main/install.sh | sh -s -- --uninstall
```
**Windows (PowerShell):**
```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`.
## Common commands
| 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`, β¦).
## Core components & how it works
```
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-workspace` itself: 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 β `sync` refuses to run against a modified read-only source and
`verify` flags 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** β `sync` resolves each revision to a SHA and writes
`git-workspace.lock.yaml`. Commit it, and anyone (or CI) reproduces the
exact tree with `sync --locked`: in that mode the engine checks out the
*locked* SHA verbatim (a floating revision like `main` advancing upstream is
ignored), requires the config's source set, `url` and `revision` to match the
lock, and never rewrites it. `verify` is 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 `guard` hook blocks force-adding assembly directories or embedded git
repositories into the outer repo.
- **Release channel** β installers pin the latest release tag, and
`git-workspace update` compares your version against it and upgrades in
place.
## Contributing
Development needs nothing but Python 3, PyYAML, and git β run the CLI straight
from the clone:
```bash
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.yaml
```
Guidelines:
- 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` β push the tag; installers and `update` pick 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