You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Add an editor-friendly Git working tree review for vendored patches #1283
dfetch diff can generate patch files for local changes to vendored projects, but large patches can be difficult to review as standalone files. A single patch may touch many files and hunks, making it hard for maintainers to inspect exactly what differs between the clean upstream source and the patched vendored source.
Reviewing the same changes as a Git working tree would make the workflow easier to navigate: editors such as VS Code can group changes by file, show side-by-side diffs, and let users inspect each modified file with their normal source control tools.
Proposal
Add a command that materializes a temporary Git repository for patch review.
Example:
dfetch review-patch SomeProject --code
Suggested default behavior:
Create a temporary review directory.
Fetch the selected project without applying patches.
Initialize a Git repository and commit that clean upstream state.
Apply the project patches.
Leave the working tree dirty with exactly the patch differences.
Optionally open the review directory in VS Code.
This would let users inspect the patch as normal Git working-tree changes.
Thanks for the write-up! A nice feature I haven't thought of :)
Before proposing an alternative I want to make sure I understand the goal correctly. My assumption: you want to walk through the patches one by one to review what each one contributes, rather than review the combined diff of all patches at once. If that's wrong, please correct me.
With that assumption, here are the constraints I'd like to work within:
No external state. A temporary directory with its own Git repo means dfetch has to track it, clean it up, and handle the case where it goes stale. State makes everything harder.
No editor coupling. Launching VS Code (or any editor) from a CLI tool is fragile. It won't work in CI, remote sessions, or for users who prefer something else. The tool should put the files in the right state; the user opens whatever they want.
I briefly considered adopting quilt as a dependency, since its push/pop/goto model is exactly the right mental model here. The patches dfetch already generates are standard unified diff format, which is quilt-compatible. But this makes it too complicated and fragile as well.
Creating an entire copy of the project in a temp directory also feels heavy for what is essentially a navigation problem.
Proposed alternative: dfetch rewind-patch
A new command that moves the vendored project directory to a specific point in its patch stack, directly in place, with no copy:
dfetch rewind-patch mylib 0 # clean upstream, no patches
dfetch rewind-patch mylib 1 # first patch applied
dfetch rewind-patch mylib my-fix.patch # up to and including named patch
dfetch rewind-patch mylib -i # interactive TUI picker
The interactive mode (-i) shows a scrollable list of the patch stack. Navigate with arrow keys, press Enter to jump to that state:
Patch stack: mylib
(unpatched)
fix-null-check.patch
▶ add-feature.patch <- current
↑/↓ navigate Enter jump to state Esc exit
After pressing Up and Enter:
Patch stack: mylib
(unpatched)
▶ fix-null-check.patch <- current
add-feature.patch
↑/↓ navigate Enter jump to state Esc exit
Your editor refreshes automatically because the files change in place. There is no copy to manage.
Preconditions (same as update-patch): must be inside a VCS superproject with no uncommitted changes in the project directory. Recovery is trivial: dfetch update -f <project> or a VCS undo restores the original state, with no dfetch-managed cleanup needed.
Side note: existing workaround with format-patch and git am
If you primarily want to see each patch as a proper Git commit, there is already a partial path with existing dfetch commands. dfetch format-patch produces email-style patches (one per file) that git am can apply as individual commits. So you could clone the upstream repo yourself, run dfetch format-patch <project>, and pipe the result through git am to get one commit per patch in a real Git history you can browse with any tool. It requires manual setup and only works for Git-backed projects, but it may already cover your use case without waiting for a new command.
On naming: review-patch describes why you might use the command, not what it does. The existing commands update-patch and format-patch name what happens to the patch. rewind-patch follows that pattern. But I'm still not completely sold on the name.
Thanks, that helps. I think my goal is slightly different from your assumption.
I am not mainly trying to walk through the patch stack one patch at a time. That could be useful, but my primary need is to review the final vendored result against clean upstream in an editor-friendly way.
In other words, I want to answer:
“What exactly is different between upstream as fetched by dfetch, and the same project after all dfetch patches have been applied?”
The reason is that reading .patch files directly becomes hard when they touch many files and hunks. What I would like is the same experience I get when reviewing normal Git working tree changes in VS Code:
a file tree showing Modified / Added / Deleted files
click a file
see a side-by-side diff
left side: clean upstream
right side: patched vendored result
For that use case, rewind-patch sounds useful for navigating the patch stack, but I am not sure it gives the same review experience. If it rewinds the real vendored directory in place, the editor may show a reverse diff against the current committed vendored state, rather than a clean “upstream -> patched result” comparison.
So my main request is not editor coupling specifically, and it does not have to be VS Code-only. The core request is: provide a simple command that prepares the project in a state where any Git-aware editor can show the full upstream-vs-patched diff as normal working tree changes.
If there is already a way to do that with existing dfetch commands, I may have missed it.
I tested the prototype on my project with a few dfetch patch stacks and so far I have not noticed any unexpected behavior. Reviewing the result through git diff / VS Code is much easier than reading the patch files directly.
One thing that could make this more flexible: when passing multiple projects, review-patch currently reviews them sequentially, pausing and restoring one project before moving to the next. That behavior makes sense as a safe default.
Would you consider adding an explicit mode to review multiple projects in a single pass? Naming aside, something like:
dfetch review-patch --mode combined project-a project-b
# or, with no project names, all projects from dfetch.yaml in one pass
dfetch review-patch --mode combined
The idea would be to validate all selected projects first, stage the clean upstream state for all of them, apply all selected patch stacks, and then pause once. That would let a Git-aware editor show the full upstream-vs-patched diff across multiple vendored projects in a single review pass.
I realize this may complicate restore/error handling, so I am not sure whether it fits the command design. But from a user perspective, it would be useful when reviewing the overall impact of several vendored patch stacks together.
One small UX/documentation note: in VS Code it is important to review the regular "Changes" view, not "Staged Changes", because the staged diff is an implementation detail and appears reversed. Once I realized that, the workflow made sense.
I expect I will use this feature a lot. I will report back if I run into any edge cases.
Thanks again for your feedback. I've updated the docs.
I'm still pondering on a better name. I want to keep the flexibility to add edit capabilty to it. Naming always remains one of the hardest problems in software :).
I'm also looking at your combined suggestion, my preference would be if 1 project given, then as-is currently, if 0 it means all projects with patches, else the number of projects given. For TUI a tree structure could make it possible to select any combination of patches applied to the projects:
The command re-executes a sequence of patches against a clean upstream state to show their cumulative effect, then tears everything down and restores the original state on exit, so the name needs to describe that mechanical action rather than the goal of reviewing or inspecting, and it needs to read naturally with a --count argument since you're typically stepping through a subset of a multi-patch series rather than acting on one patch in isolation, which rules out singular phrasing like review-patch and argues for a plural like *-patches. Among the verb candidates, apply was the closest competitor but was rejected because in git's own vocabulary apply/am connote a persistent change, exactly the opposite of what this command does, since nothing should still be applied once it exits; try and simulate were considered for honestly signaling the non-destructive, temporary nature of the operation, but they describe the property of the execution (safe, reversible) rather than the execution itself, and don't capture that the patches are being run in sequence against a known base; step and run were too generic to convey that patches already exist and are being re-executed rather than freshly authored or run for the first time. replay was chosen because it's the one verb that simultaneously captures sequential re-execution (a patch series is replayed in order, like a log or a recording), implies a known, deterministic input being reproduced rather than something new being created, and is naturally compatible with stepping through a subset via --count (dfetch replay-patches my-project --count 3 reads as "replay the first three patches," not "review the first three" or "apply the first three," both of which carry the wrong implications). The resulting name, replay-patches, names the mechanical action rather than the user's goal, takes the plural naturally, and, while it doesn't explicitly assert the non-destructive/temporary behavior the way try-patches would, is close enough to that connotation (replaying something doesn't inherently commit it to permanent state) that the trade-off was judged acceptable in favor of better describing what the command actually does step by step.
Thanks! I tested the updated prototype and everything worked as expected.
I tried:
replaying a single project
stepping through its patches interactively
replaying multiple projects in a single combined review
using the per-project name:N syntax
using the combined interactive TUI
replaying all patched projects by omitting the project names
The combined mode is exactly what I had in mind, and the repository is restored correctly when the command exits.
The interactive tree also feels natural: switching projects with ↑/↓ and stepping through patches with ←/→ worked well.
replay-patches now seems like a good name to me. It describes the operation more accurately than review-patch, especially now that the command can replay only part of each patch stack.
I did not encounter any unexpected behavior in my tests. Thanks for implementing the suggestion!
Activity
spoorcc commentedon Jun 17, 2026
Thanks for the write-up! A nice feature I haven't thought of :)
Before proposing an alternative I want to make sure I understand the goal correctly. My assumption: you want to walk through the patches one by one to review what each one contributes, rather than review the combined diff of all patches at once. If that's wrong, please correct me.
With that assumption, here are the constraints I'd like to work within:
I briefly considered adopting quilt as a dependency, since its push/pop/goto model is exactly the right mental model here. The patches dfetch already generates are standard unified diff format, which is quilt-compatible. But this makes it too complicated and fragile as well.
Creating an entire copy of the project in a temp directory also feels heavy for what is essentially a navigation problem.
Proposed alternative:
dfetch rewind-patchA new command that moves the vendored project directory to a specific point in its patch stack, directly in place, with no copy:
Examples:
The interactive mode (-i) shows a scrollable list of the patch stack. Navigate with arrow keys, press Enter to jump to that state:
After pressing Up and Enter:
Your editor refreshes automatically because the files change in place. There is no copy to manage.
Preconditions (same as
update-patch): must be inside a VCS superproject with no uncommitted changes in the project directory. Recovery is trivial:dfetch update -f <project>or a VCS undo restores the original state, with no dfetch-managed cleanup needed.Side note: existing workaround with
format-patchandgit amIf you primarily want to see each patch as a proper Git commit, there is already a partial path with existing dfetch commands.
dfetch format-patchproduces email-style patches (one per file) that git am can apply as individual commits. So you could clone the upstream repo yourself, rundfetch format-patch <project>, and pipe the result through git am to get one commit per patch in a real Git history you can browse with any tool. It requires manual setup and only works for Git-backed projects, but it may already cover your use case without waiting for a new command.On naming: review-patch describes why you might use the command, not what it does. The existing commands update-patch and format-patch name what happens to the patch. rewind-patch follows that pattern. But I'm still not completely sold on the name.
sawachikaminoru commentedon Jun 17, 2026
Thanks, that helps. I think my goal is slightly different from your assumption.
I am not mainly trying to walk through the patch stack one patch at a time. That could be useful, but my primary need is to review the final vendored result against clean upstream in an editor-friendly way.
In other words, I want to answer:
“What exactly is different between upstream as fetched by dfetch, and the same project after all dfetch patches have been applied?”
The reason is that reading
.patchfiles directly becomes hard when they touch many files and hunks. What I would like is the same experience I get when reviewing normal Git working tree changes in VS Code:For that use case,
rewind-patchsounds useful for navigating the patch stack, but I am not sure it gives the same review experience. If it rewinds the real vendored directory in place, the editor may show a reverse diff against the current committed vendored state, rather than a clean “upstream -> patched result” comparison.So my main request is not editor coupling specifically, and it does not have to be VS Code-only. The core request is: provide a simple command that prepares the project in a state where any Git-aware editor can show the full upstream-vs-patched diff as normal working tree changes.
If there is already a way to do that with existing dfetch commands, I may have missed it.
spoorcc commentedon Jun 18, 2026
Thanks for your feedback! I'm still thinking, but started a prototype to discover a workflow that works and fits for dfetch
spoorcc commentedon Jun 19, 2026
There is a prototype ready in the linked pr. I would love some feedback:
You can install it (in a venv preferentially) by doing
any feedback is welcome!
sawachikaminoru commentedon Jun 19, 2026
Thanks! This is exactly what I needed.
I tested the prototype on my project with a few dfetch patch stacks and so far I have not noticed any unexpected behavior. Reviewing the result through
git diff/ VS Code is much easier than reading the patch files directly.One thing that could make this more flexible: when passing multiple projects,
review-patchcurrently reviews them sequentially, pausing and restoring one project before moving to the next. That behavior makes sense as a safe default.Would you consider adding an explicit mode to review multiple projects in a single pass? Naming aside, something like:
dfetch review-patch --mode combined project-a project-b # or, with no project names, all projects from dfetch.yaml in one pass dfetch review-patch --mode combinedThe idea would be to validate all selected projects first, stage the clean upstream state for all of them, apply all selected patch stacks, and then pause once. That would let a Git-aware editor show the full upstream-vs-patched diff across multiple vendored projects in a single review pass.
I realize this may complicate restore/error handling, so I am not sure whether it fits the command design. But from a user perspective, it would be useful when reviewing the overall impact of several vendored patch stacks together.
One small UX/documentation note: in VS Code it is important to review the regular "Changes" view, not "Staged Changes", because the staged diff is an implementation detail and appears reversed. Once I realized that, the workflow made sense.
I expect I will use this feature a lot. I will report back if I run into any edge cases.
spoorcc commentedon Jun 23, 2026
Thanks again for your feedback. I've updated the docs.
I'm still pondering on a better name. I want to keep the flexibility to add edit capabilty to it. Naming always remains one of the hardest problems in software :).
I'm also looking at your combined suggestion, my preference would be if 1 project given, then as-is currently, if 0 it means all projects with patches, else the number of projects given. For TUI a tree structure could make it possible to select any combination of patches applied to the projects:
For non-interactive mode a
:Nsuffix in the project name could also be used:ben-edna commentedon Jun 23, 2026
The command re-executes a sequence of patches against a clean upstream state to show their cumulative effect, then tears everything down and restores the original state on exit, so the name needs to describe that mechanical action rather than the goal of reviewing or inspecting, and it needs to read naturally with a --count argument since you're typically stepping through a subset of a multi-patch series rather than acting on one patch in isolation, which rules out singular phrasing like review-patch and argues for a plural like *-patches. Among the verb candidates, apply was the closest competitor but was rejected because in git's own vocabulary apply/am connote a persistent change, exactly the opposite of what this command does, since nothing should still be applied once it exits; try and simulate were considered for honestly signaling the non-destructive, temporary nature of the operation, but they describe the property of the execution (safe, reversible) rather than the execution itself, and don't capture that the patches are being run in sequence against a known base; step and run were too generic to convey that patches already exist and are being re-executed rather than freshly authored or run for the first time. replay was chosen because it's the one verb that simultaneously captures sequential re-execution (a patch series is replayed in order, like a log or a recording), implies a known, deterministic input being reproduced rather than something new being created, and is naturally compatible with stepping through a subset via --count (dfetch replay-patches my-project --count 3 reads as "replay the first three patches," not "review the first three" or "apply the first three," both of which carry the wrong implications). The resulting name, replay-patches, names the mechanical action rather than the user's goal, takes the plural naturally, and, while it doesn't explicitly assert the non-destructive/temporary behavior the way try-patches would, is close enough to that connotation (replaying something doesn't inherently commit it to permanent state) that the trade-off was judged acceptable in favor of better describing what the command actually does step by step.
ben-edna commentedon Jun 24, 2026
The prototype branch was updated with the new name, combined mode
sawachikaminoru commentedon Jun 25, 2026
Thanks! I tested the updated prototype and everything worked as expected.
I tried:
name:NsyntaxThe combined mode is exactly what I had in mind, and the repository is restored correctly when the command exits.
The interactive tree also feels natural: switching projects with ↑/↓ and stepping through patches with ←/→ worked well.
replay-patchesnow seems like a good name to me. It describes the operation more accurately thanreview-patch, especially now that the command can replay only part of each patch stack.I did not encounter any unexpected behavior in my tests. Thanks for implementing the suggestion!
spoorcc commentedon Jun 25, 2026
Thank you for your feedback, i'm cleaning up the implementation a little bit, but will be part of 0.15.0