git-cross is a small tool for pulling part of one Git repository into another with git worktree plus rsync.
It is for the cases where you want real files in your tree, not a gitlink, and still want a clean path back upstream.
git-cross is useful when you want to:
- vendor only one subdirectory from another repository
- keep vendored code as normal files in your own repository
- pull upstream updates without converting your repo into a submodule setup
- push changes back to a fork or upstream project without manual worktree plumbing
- let AI tools work on a mounted subfolder instead of your full repository
Compared with submodules or subrepo-style flows, the tradeoff is simple: git-cross keeps files physical and visible in your repo, and tracks the upstream relationship separately through hidden worktrees and Crossfile.
- Pull
docs/from an upstream project intovendor/docs - Keep a shared app template in
vendor/templateand customize it locally - Work on an upstream library inside
vendor/libwith normal editor tooling - Let an AI sandbox mount only
vendor/libinstead of the whole repo - Publish your local combined result to your own
origin, while still being able to send a clean PR or MR upstream later
The repository ships three implementations:
- Go: primary production implementation
- Just/Fish: readable reference implementation
- Rust: experimental parity implementation
For normal usage, prefer the Go binary.
just installManual build:
cd src-go
go build -o git-cross-go main.go
git config --global alias.cross "!$(pwd)/git-cross-go"just install shelljust install rust# 1. Register upstream
git cross use demo https://github.com/example/demo.git
# 2. Materialize one directory locally
git cross patch demo:docs vendor/docs
# 3. Inspect local state
git cross status
git cross diff vendor/docs
# 4. Pull new upstream changes later
git cross sync vendor/docsgit-cross keeps four things in sync:
- Your main repository
- A hidden worktree for each upstream patch under
.cross/worktrees/ - A local physical directory such as
vendor/docs - A
Crossfilethat records how to rebuild the setup
In practice:
- your editor sees normal files
- AI tools can work on normal files
- upstream history stays in the hidden worktree
git cross replaycan reconstruct the setup later
One common pattern is to keep local-only files next to upstream-managed files.
Example:
git cross use app https://github.com/example/app.git
git cross patch app:src vendor/app
cat > vendor/app/.crossignore <<'EOF'
.env
compose.override.yaml
EOFRule of thumb:
- a plain basename entry such as
.envmatches that name in any subdirectory under the patch - a directory entry such as
configorconfig/matches that directory tree - a basename glob such as
*.envalso matches anywhere under the patch - this is intentionally simpler than full
.gitignoresemantics
What this does today:
git cross statusshowsOverridefor that patchgit cross diff vendor/appprints manualgit diff --no-index ...commands for the override paths- your local files stay in place for normal local work
This is intentionally conservative. .crossignore entries are review signals, not a substitute for review before sync or push.
If you keep secrets or machine-local files in a patched directory, review them explicitly before sending changes upstream.
There are two separate publish flows.
This is just normal Git in your main repository:
git add vendor/app
git commit -m "Update vendored app and local overlays"
git push origin mainYour own repository stores the final combined result, including local overlay files if you choose to commit them there.
When you want to contribute upstream-managed changes back:
git cross diff vendor/app
git cross push vendor/app --message "Fix upstream bug"Recommended pattern:
- Track a writable fork with
git cross use. - Patch from that fork into your local tree.
- Keep local-only overlay files out of the upstream contribution.
- Run
git cross pushfor the vendored path. - Open a PR or MR from your fork branch to the original upstream project.
This lets your main repo keep its local opinionated result while the upstream contribution stays focused.
- Overview
- Tutorial: Local Overlays And Upstream Contribution
- Tutorial: Whole Upstream Into A Local Directory
- Tutorial: Migrate A Private Fork To git-cross
- Sandbox Kits
git cross use <name> <url>Register an upstream remote alias and detect its default branch.
git cross patch <remote>:<path> [local_dest]Create or reuse a hidden worktree, sparse-check out the upstream path, and sync it into your local directory.
git cross sync [path]Pull upstream changes into the local patched directory.
git cross diff [path]Compare local files with the hidden worktree copy.
git cross statusShow local diff state, upstream divergence, and conflicts.
git cross push [path] [--force] [--message "msg"]Sync local changes back into the worktree, commit them there, and push to the upstream remote.
git cross replayRebuild the full setup from Crossfile.
git cross remove <path>Remove one patch and clean up local state.
git cross prune [remote]Remove unused remotes, stale worktrees, or all patches for one remote.
removeandprunenow guard against deleting repo root contents when a patch targets.- whole-upstream patching with
remote:.andremote:/works for vendoring into local directories - override markers in
.crossignorecurrently affect review surfaces:statusanddiff - if you are experimenting with root-target overlay workflows, treat them as advanced usage and verify results carefully
This repo already includes agent guidance for AI coding tools:
- shared repo roles in
.agents/ - Claude-facing entrypoints in
.claude/ - OpenCode-native skills in
.opencode/skills/
Current shared roles:
- maintainer
- feature spec writer
- safety reviewer
- regression tester
If you want an AI agent to work only on a vendored subtree, mount just that subtree in a sandbox and keep the main .git state on the host.
This repo includes repo-local starter kits under sbx-kits/.
Examples:
sbx run opencode --kit ./sbx-kits/opencode
sbx run claude --kit ./sbx-kits/claudeWhy use a kit:
- safer trial path for people who do not want to install a new tool globally first
- reproducible sandbox setup checked into the repository
- easy place to add sandbox-local agent config later
See sbx-kits/README.md for the structure, starter kits, and intended workflow.
High level:
- Just/Fish is the readable behavior reference
- Go is the main production CLI
- Rust is parity-oriented and still experimental
Detailed architecture notes live in docs/overview.md.
MIT