鵺 — a folkloric chimera assembled from the limbs of disparate beasts.
nue is a vendoring tool for git. You declare which fragments of which
upstream repos make up your project; nue sync pulls each upstream,
filters its history, and replays the resulting commits onto your branch
with full author / message / commit-graph fidelity. Vendored files end up in
your git history as ordinary tracked content, ready to commit, review, and
ship.
- No daemon, no FUSE, no kernel modules — single Rust binary
- Powered by josh as the history-filter engine
- File-level mapping (precise) and tree-level mapping (recursive)
- Bidirectional:
nue pushlifts host-side edits back to an upstream - State lives in
Nue-Source-<name>: <sha>commit trailers (à la CopybaraGitOrigin-RevId) — no separate state file
# install nue
cargo install --path .
# install josh-filter (history-filter engine)
cargo install --git https://github.com/josh-project/josh \
--bin josh-filter josh-cli
# in your git repo, write nue.yaml:
cat > nue.yaml <<'EOF'
version: 1
sources:
common:
url: git@github.com:myorg/common-libs.git
ref: refs/heads/main
grafts:
- from: common
files:
- {src: utils/logger.py, dst: libs/log.py}
trees:
- {src: schemas/, dst: vendor/schemas/}
EOF
# pull upstream, filter, replay onto your branch
nue syncEnd-to-end self-contained demo: ./examples/demo.sh.
| Term | Meaning |
|---|---|
| source | an upstream repo declared in sources: |
| graft | one (upstream path → host path) mapping |
| file graft / tree graft | single file vs directory grafts |
| host | your work repo (term-of-art for "graft recipient") |
| sync | pull sources, filter, replay onto host HEAD |
| push | host edits → upstream commit on refs/heads/nue-push/<source> |
nue.yaml ──► Manifest ──► filter_spec ──► josh filter string
│
▼
.git/nue/<src>.git (bare clone) ──┬── git fetch
├── josh-filter <spec> → refs/nue/filtered
└── git fetch into host → refs/nue/<src>/filtered
│
▼
host repo HEAD
(git merge with
Nue-Source-<src>: trailer)
No daemon, no IPC, no codegen. All state:
.git/nue/<src>.git/— bare clones (one per source, shared across worktrees)Nue-Source-<src>: <sha>trailer on the latest sync's merge commit
See docs/design.md for the longer story.
nue sync # pull sources, filter, replay onto HEAD
nue push <source> # snapshot host edits → upstream branch
# refs/heads/nue-push/<source>
nue debug filter-spec # show the generated josh filter (debugging)
# common flags:
nue --repo PATH ... # operate on PATH (default: cwd)
nue --manifest FILE ... # use FILE instead of nue.yaml
Pre-1.0. Currently working:
syncfor file and tree grafts (multi-source orchestration)pushfor file grafts (single-commit snapshot)- End-to-end smoke test (
./examples/demo.sh)
Not yet:
- Tree graft push (only file grafts can push)
- Conflict policy on local edits vs upstream changes
eject/which/statussubcommands- Authentication helpers for private remotes
- Pre-built
josh-filterdistribution
The project previously implemented this concept via a FUSE daemon. That
architecture has been replaced; see git history if you need it (last commit
of the FUSE branch is cabd706).
| Tool | Why nue exists anyway |
|---|---|
git submodule |
whole-repo granularity; we want file/dir-level |
git subtree |
tree-only, awkward to update, no replay control |
josh link (in josh-cli) |
works; manifest is per-dir .link.josh; view-oriented modes. nue trades that for one yaml + Nue-Source trailer that survives PR review |
| Copybara | feature-rich and battle-tested at Google; JVM/Bazel, Starlark config |
| vendir | snapshot vendoring; no commit replay |
Apache-2.0