Summary
When a project carries a stack of multiple patches, update-patch can only regenerate the last one. There is no supported way to record a change into an intermediate patch. I'd like update-patch to accept a target patch, so a change that belongs to an earlier patch can be recorded there, with the later patches rebased on top to keep the stack consistent.
Background
Since 0.12.0 a project can carry a list of patches (a stack). Splitting local modifications into several concern-focused patches is genuinely useful: each patch stays small, readable, and individually upstreamable, and format-patch already leans into treating patches as coherent, contributable changesets.
A typical concern-separated stack for a vendored library might look like:
0001-rename-namespace.patch # adapt symbols to our namespace
0002-swap-logging-backend.patch # replace the logging backend; defines DEFAULT_LOG_LEVEL = "info"
0003-local-project-overlay.patch # small project-specific tweaks
Problem
Say I now want to change DEFAULT_LOG_LEVEL from "info" to "debug". That constant is introduced by 0002, so 0002 is its correct home.
After making the edit in the working tree:
update-patch regenerates only the last patch, folding the change into 0003 as an override that re-changes a line 0002 already owns. 0003 now contradicts 0002 — a smell that defeats the point of a concern-separated stack.
- The only correct alternative today is to hand-edit
0002.patch: fix the added line, and also fix the file's index <blob>..<blob> hash and any hunk offsets by hand. Fragile and easy to get subtly wrong, especially for larger edits.
Proposed behavior
Let update-patch take a target patch, e.g.:
dfetch update-patch <project> --patch <index|patch-name>
- With no target it behaves exactly as today (regenerate the last patch), so this is fully backward compatible.
- With a target
K, it records the current working-tree change into patch K and rebases K+1..N on top, re-applying each. If a later patch genuinely depends on the changed lines the conflict is surfaced rather than silently corrupting context — the same honest signal git rebase gives.
Because the regeneration goes through git, the index blob hashes and hunk offsets of every affected patch file are recomputed automatically, so the whole stack stays consistent with no hand-editing.
For the example above, update-patch <project> --patch 0002-swap-logging-backend would update only 0002.patch; 0003 (which doesn't touch that line) rebases cleanly and stays unchanged.
Relation to #883
#883 (edit-patch) is the closest existing work, but it targets the patch (singular). In a stack its reverse/stage/re-apply flow leaves the baseline at "upstream + 0001 + 0002" and the worktree at "…+ 0003", so it still regenerates the last patch — it doesn't target an intermediate patch or rebase the later ones. The two could share machinery: an interactive edit-patch flow fits the "clean tree, take me to patch K to edit it" case, while the extension proposed here fits the "I already made the change; record it into patch K" case.
Constraints
Ideally this stays in-place on the vendored directory with no external state (no temp repo/worktree for dfetch to track and clean up), recoverable with dfetch update -f <project>. The reverse/stage/re-apply mechanism sketched in #883 seems extendable to a stack: reverse N..K, regenerate K from the working-tree change, then re-apply K+1..N in place — that last step being the rebase, where any conflict surfaces.
Alternatives considered
- Hand-editing the intermediate
.patch — works for one-liners but is fragile (manual blob hashes / offsets) and error-prone at scale.
- Overriding in the last patch — keeps
update-patch happy but produces contradictory, redundant patches and erodes the concern separation.
- Restructuring so edits always land in the last patch — gives up the benefit of a concern-separated stack.
Summary
When a project carries a stack of multiple patches,
update-patchcan only regenerate the last one. There is no supported way to record a change into an intermediate patch. I'd likeupdate-patchto accept a target patch, so a change that belongs to an earlier patch can be recorded there, with the later patches rebased on top to keep the stack consistent.Background
Since 0.12.0 a project can carry a list of patches (a stack). Splitting local modifications into several concern-focused patches is genuinely useful: each patch stays small, readable, and individually upstreamable, and
format-patchalready leans into treating patches as coherent, contributable changesets.A typical concern-separated stack for a vendored library might look like:
Problem
Say I now want to change
DEFAULT_LOG_LEVELfrom"info"to"debug". That constant is introduced by0002, so0002is its correct home.After making the edit in the working tree:
update-patchregenerates only the last patch, folding the change into0003as an override that re-changes a line0002already owns.0003now contradicts0002— a smell that defeats the point of a concern-separated stack.0002.patch: fix the added line, and also fix the file'sindex <blob>..<blob>hash and any hunk offsets by hand. Fragile and easy to get subtly wrong, especially for larger edits.Proposed behavior
Let
update-patchtake a target patch, e.g.:K, it records the current working-tree change into patchKand rebasesK+1..Non top, re-applying each. If a later patch genuinely depends on the changed lines the conflict is surfaced rather than silently corrupting context — the same honest signalgit rebasegives.Because the regeneration goes through git, the
indexblob hashes and hunk offsets of every affected patch file are recomputed automatically, so the whole stack stays consistent with no hand-editing.For the example above,
update-patch <project> --patch 0002-swap-logging-backendwould update only0002.patch;0003(which doesn't touch that line) rebases cleanly and stays unchanged.Relation to #883
#883 (
edit-patch) is the closest existing work, but it targets the patch (singular). In a stack its reverse/stage/re-apply flow leaves the baseline at "upstream + 0001 + 0002" and the worktree at "…+ 0003", so it still regenerates the last patch — it doesn't target an intermediate patch or rebase the later ones. The two could share machinery: an interactiveedit-patchflow fits the "clean tree, take me to patch K to edit it" case, while the extension proposed here fits the "I already made the change; record it into patch K" case.Constraints
Ideally this stays in-place on the vendored directory with no external state (no temp repo/worktree for dfetch to track and clean up), recoverable with
dfetch update -f <project>. The reverse/stage/re-apply mechanism sketched in #883 seems extendable to a stack: reverseN..K, regenerateKfrom the working-tree change, then re-applyK+1..Nin place — that last step being the rebase, where any conflict surfaces.Alternatives considered
.patch— works for one-liners but is fragile (manual blob hashes / offsets) and error-prone at scale.update-patchhappy but produces contradictory, redundant patches and erodes the concern separation.