etz
etz is a CLI for managing multi-repo workspaces where the parent folder is not a git repo and each direct child folder is an independent git repo.
It creates coordinated git worktrees under:
parent/.etz/workspaces/<workspace>/<repo>
Commands
etz initetz add <workspace> --branch <branch> [--no-copy-root]etz listetz refresh [--check] [--json]etz status [workspace] [--changed] [--summary] [--json]etz commit [workspace] -m "msg" [--all] [--dry-run] [--json]etz push [workspace] [--dry-run] [--json]etz remove <workspace> [--force]etz pruneetz doctor [--fix] [--json]
Behavior Highlights
- Repo discovery is direct children only.
- Missing branch on
addis auto-created from each repo's detected default branch. refreshre-discovers direct-child repos and updates the manifest lock file.refresh --checkreports drift and exits non-zero without mutating files.addcopies non-repo files/directories from the parent root into the workspace root by default.- Use
--no-copy-rootto disable that copy behavior. - Optional
.etzcopyand.etzignorepatterns let you include/exclude root files copied into a workspace. addandremoveare fail-fast and attempt rollback on partial failures.- If you run
etzfrom inside.etz/workspaces/<workspace>/...,status,commit, andpushinfer the workspace automatically. statusincludes per-repo staged/unstaged/untracked counts.status --changedfilters to changed repos;status --summaryprints condensed totals.commitworks across repos in one workspace:- default: commits only repos with staged changes
- smart fallback: if nothing is staged but tracked files changed, it auto-stages tracked changes (
git add -u) and commits --all: stages all tracked + untracked changes (git add -A) first--dry-run: shows what would be committed and what would be auto-staged, without changing any repo- on failure in later repos, previously created commits from this run are rolled back with
git reset --soft HEAD~1
pushpushes repos that are ahead of upstream;--dry-runpreviews push candidates.doctor --fixcan prune stale workspace state entries and attempt branch realignment where safe.- State is persisted in:
.etz/config.toml.etz/manifest.lock.toml.etz/state.toml
Quick Start
# inside parent folder that contains git child repos
# after making/staging changes
# cleanup
Publishing (crates.io + Homebrew)
Tagged releases are automated by .github/workflows/release.yml.
One-time setup
- Create a crates.io API token with publish scope and add it to repo secrets as
CARGO_REGISTRY_TOKEN. - Create a GitHub token that can push to
snipeship/homebrew-tapand add it asHOMEBREW_TAP_GITHUB_TOKEN. - Ensure
snipeship/homebrew-tapexists and contains aFormula/directory.
Release flow
- Bump
[package].versioninCargo.toml. - Commit and push to
main. - Tag the commit with the same version prefixed by
v(for examplev0.2.0) and push the tag.
The workflow will:
- run tests
- build
etzbinaries for Linux x86_64, macOS x86_64, and macOS arm64 - create a GitHub Release with tarballs +
SHA256SUMS - publish the crate to crates.io
- update
snipeship/homebrew-tap/Formula/etz.rb
After release, users can install with: