GitTwin
Run multiple git commits, branches, or tags of the same FastAPI application side by side, each in its own isolated environment — for comparison, debugging, regression testing, and demonstrations.
Status: working MVP. gittwin run/gittwin compare actually boot real
FastAPI apps today. Framework support is currently FastAPI only — see
Supported frameworks below.
Why
Reproducing "it worked on commit X but not on commit Y" usually means stashing changes, checking out refs one at a time, and juggling ports, dependencies, and env files by hand. GitTwin makes that a single command:
gittwin compare HEAD abc123
HEAD -> http://127.0.0.1:8000
abc123 -> http://127.0.0.1:8001
Under the hood, each ref gets its own git
worktree, its own uv-managed
virtual environment with its own dependencies installed, and its own port
— so multiple versions of your app run side by side without one clobbering
another or disturbing your current branch.
Install
uv add gittwin
pip install gittwin
Usage
gittwin run <ref> # launch one ref, prints its URL
gittwin compare <ref1> <ref2> ... # launch two or more refs side by side
gittwin list # list worktrees gittwin has created
gittwin stop <ref> # stop one running instance
gittwin clean # stop everything, remove all worktrees/envs
gittwin doctor # check git and uv are installed
gittwin about
gittwin --version
<ref> accepts any commit SHA, branch name, or tag. An invalid ref fails
immediately with a clear error instead of a raw git traceback.
Example
cd my-fastapi-project
gittwin compare HEAD main
# HEAD: creating worktree...
# main: creating worktree...
# HEAD: creating environment...
# main: creating environment...
# HEAD: installing dependencies...
# main: installing dependencies...
# HEAD: starting on port 8000...
# main: starting on port 8001...
# ┌──────┬───────────────────────┐
# │ Ref │ URL │
# ├──────┼───────────────────────┤
# │ HEAD │ http://127.0.0.1:8000 │
# │ main │ http://127.0.0.1:8001 │
# └──────┴───────────────────────┘
gittwin clean # tear both down when you're done
Supported frameworks
FastAPI only, for now. gittwin run/gittwin compare detect FastAPI
via a fastapi entry in your pyproject.toml dependencies, and boot your
app with uvicorn <module>:<app> (convention: main:app). Flask, Django,
Node.js, Docker-based apps, and other languages are on the backlog, not
implemented yet.
How it works
- Worktrees: each ref is checked out into
<repo>/.gittwin/worktrees/<ref>, so multiple refs can be checked out simultaneously without one clobbering another.gittwin listshows only worktrees gittwin created — your main checkout is never listed as one of them. - Environments: each worktree gets its own
uv-managed venv under<repo>/.gittwin/envs/<ref>, with that ref's ownpyproject.tomldependencies installed into it — so different refs can depend on different (even incompatible) package versions. - Ports: each instance gets a free port automatically, allocated from
gittwin.toml's configured range (default8000-8999), with no collisions even when launching several refs concurrently viacompare. - Cleanup:
gittwin stop <ref>/gittwin cleanterminate the running process(es) and remove the worktree(s) and env(s) they used. If setup for a ref fails partway through, gittwin removes that worktree again rather than leaving a half-provisioned one behind.
Development
This project uses uv for dependency management.
uv sync --extra dev # install package + dev deps into .venv
uv run pytest -q # run tests
uv run gittwin about # run the CLI
Metadata
Release files for gittwin 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| gittwin-0.2.0.tar.gz | 20.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| gittwin-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 34.6 kB
Release files / gittwin-0.2.0.tar.gz
| Download URL | gittwin-0.2.0.tar.gz |
|---|---|
| Size | 20.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7ff7984019a265e8f342901d947ce45b8820126e4fd2541748926d3459f0e563
|
|
BLAKE2b-256 checksum How to use checksums |
de443e321eec6359539076523b58c9a1f6e61e54e44bd775934cf3bdf36bec84
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / gittwin-0.2.0-py3-none-any.whl
| Download URL | gittwin-0.2.0-py3-none-any.whl |
|---|---|
| Size | 13.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
58ac03dfb22911c47be8c4347d7c98b76f421b35c4c105f45953b62db3fc4c37
|
|
BLAKE2b-256 checksum How to use checksums |
e97f0a6c1e04a09d1442d76bb036742384bdbb26c2e8cedbec313020c21f5317
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|