Render targets as real worktree files: git clean/smudge filters instead of --skip-worktree
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 0
- Forks
- 0
- Avg merge
- 1h 58m
- Merged PRs (30d)
- 48
Description
Summary
Replace --skip-worktree on source-owned render targets with a per-workspace
git clean/smudge filter, so rendered files are ordinary files in the
worktree and the substitution is reversed on every git operation instead of
the file being hidden from git entirely.
Both halves already exist: render::substitute is the smudge,
render::reverse is the clean (crates/newgit-core/src/render.rs).
Why this fits
newgit-v1-mvp.md:599 — "A render reads the committed content of the path,
substitutes, and writes the result. It never reads what is currently on
disk."
A smudge filter receives exactly the committed blob on stdin. The purity rule
that was derived to make render idempotent is precisely the filter contract.
Checkout becomes render.
This is also the interposition point git actually provides, rather than a
git shim — consistent with interpose or intercept commands, don't emulate,
and it avoids the command shims that v1 deliberately defers.
Mechanism
Installed per-workspace, the same shape as the .git/info/exclude handling
for tracker paths (crates/newgit-core/src/materializer.rs:72). Both files
are untracked and per-clone, so nothing lands in the repo:
# <workspace>/.git/info/attributes
packages/db/supabase/config.toml filter=newgit-render
# <workspace>/.git/config
[filter "newgit-render"]
clean = newgit render-clean --workspace . -- %f
smudge = newgit render-smudge --workspace . -- %f
required = true
required = true is not optional: a missing or erroring newgit binary must
fail the git command loudly rather than silently committing this instance's
ports.
What this deletes
Not additive — it removes machinery:
--skip-worktreeon source paths (crates/newgit-core/src/source.rs:213)
and with it the whole What it costs, and saying so section
(newgit-v1-mvp.md:661). Hand edits to a rendered source file round-trip
and commit cleanly, because git only ever sees cleaned content. "To edit a
rendered file for real, edit it in the store repo" stops being a
limitation.- Drift detection — the recompute-and-compare at checkpoint and before
re-render. It exists only to warn that an edit is about to be lost. Under
filters the edit isn't lost. - The throwaway-index skip-worktree re-set
(crates/newgit-core/src/source.rs:236) — the leak where a fresh
GIT_INDEX_FILEdoesn't carry skip-worktree bits andgit add -Asweeps
rendered ports into a checkpoint.git add -Aagainst that index now cleans
the content itself.
newgit export reading from HEAD stays correct either way.
What has to be gotten right
-
Round-trip must be exact. If
clean(smudge(blob)) != blobbyte-for-byte,
git shows a permanent phantom modification on that file forever. The
rendered value is already required to be unique in both directions; this
makes it worth actually running the round-trip at bind and failing the
bind — same class of failure as afindthat matches zero times.Note
render::reverseis deliberately lenient about counts
(crates/newgit-core/src/render.rs:229), which is right for a clean filter
running over a file someone edited — so the guarantee has to come from the
bind-time check, not from the filter. -
Value collisions now bite constantly. If allocated port
54400happens
to appear in the committed file for an unrelated reason, clean rewrites it
too. Today that is a capture-time problem; under filters it is every
git status. -
Not everything runs filters. libgit2-based tools (JetBrains, some
editors) and jj don't — jj has no smudge/clean support. There is no jj
in the workspace path today (workspaces are plain clones), but given the
project is nominally built on jj, this constrains the direction. The v2 FUSE
projection is filter-independent and remains the real answer; this is a
better v1 stand-in than skip-worktree, and the[[render]]declaration
outlives both. -
Performance: one process spawn per rendered file per git op. Only
declared render paths, so small.filter.<name>.process(the long-running
filter protocol) is the escape hatch if it ever shows up. -
Not a security boundary.
git -c filter.newgit-render.clean= add
bypasses it — the same hole--skip-worktreehad. Consistent with do not
simulate security, but it should be stated explicitly in the spec rather
than left implied.
Work
-
newgit render-clean/newgit render-smudgesubcommands reading the
binding record by workspace path - Install
.git/info/attributes+.git/configfilter config at bind;
tear down alongside the existing exclude/skip-worktree teardown - Bind-time
clean(smudge(blob)) == blobround-trip check, failing the
bind with the file and string named - Remove skip-worktree for source-owned render paths, the throwaway-index
re-set, and drift detection - Rewrite the render section of
newgit-v1-mvp.md: fold Keeping instance
values out of everything downstream down to export + capture, drop
What it costs, and state the bypass hole
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with crates/newgit-core/src/render.rs, then inspect bind setup in crates/newgit-core/src/materializer.rs:72 and source handling around crates/newgit-core/src/source.rs:213 and :236. Trace the existing render, binding, exclude, teardown, and drift paths before implementing the listed filter subcommands and configuration. Done means bind installs and removes the filters, round-trip validation fails clearly, obsolete skip-worktree machinery is removed, and newgit-v1-mvp.md reflects the behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- git, rust
- Domain
- cli, documentation, tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100