Re: [PATCH b4 0/5] shazam: stop --resolve from silently dropping commits
Christian Brauner <[email protected]> Wed, 24 Jun 2026 10:35:51 +0200
| Newsgroups | org.kernel.linux.tools |
|---|---|
| Message-ID | <20260624-querulant-herzform-unmodern-faf5463919ef@brauner> |
On 2026-06-24 01:41 +0200, Christian Brauner wrote: > b4 shazam --resolve exists to help land a series that doesn't apply > cleanly. The problem that motivated this series is that, while resolving, > it can silently drop whole commits from the merge it produces: you end up > with a merge that is quietly missing changes, and nothing in the output > points at what went missing. > > Why they vanish > > When git am can't apply the series, the old --resolve path merged the > patches that did apply, then replayed each remaining patch with > "git apply --3way" and staged the result with "git add -u". > > git apply --3way can only do its three-way merge if the blob IDs recorded > in the patch's "index <old>..<new>" lines are present in your object > store. For patches that arrived over email those blobs usually aren't > there -- which is frequently the very reason git am -3 failed to begin > with. In that case git apply --3way falls back to a plain apply, fails > with "patch does not apply", and exits non-zero having written nothing at > all: no conflict markers, no unmerged index entries. > > The replay loop assumed any non-zero exit meant "conflict markers are in > the tree." It advanced past the patch and asked you to resolve conflicts > that did not exist, so b4 shazam --continue happily resumed at the next > patch. The skipped patch's changes never entered the merge -- they were > simply gone, with no warning. A patch that only adds a new file can > disappear the same way when it rides along with a change that can't be > applied. > > How this fixes it > > Stop replaying patches with git apply entirely. On a conflict, b4 already > leaves the in-progress git am parked in a throwaway worktree; keep it > there and finish it natively: > > cd <worktree printed by b4> > # resolve the conflicted files > git am --continue # or: git am --skip > > git am drives the whole remaining series through git's own machinery, > which stops on every patch it cannot apply and never silently skips one. > Once it is done, b4 shazam --continue fetches the fully-applied series and > merges it exactly once -- the same merge a clean b4 shazam makes. Because > every patch now goes through git am, nothing can vanish. This also brings > --resolve in line with how the review TUI already resolves conflicts. > > Since both now resolve am conflicts the same way, the series starts by > lifting the worktree plumbing the TUI already had -- detecting an > in-progress git am, and fetching the finished result out of the worktree > before dropping it -- into b4 core, and shazam reuses it rather than > growing its own copy. > > Resolving conflicts in subdirectory files > > One gap hid behind that guarantee. The series is applied in a sparse > worktree where only root-level files are materialized, and git's 3-way > merge refuses to touch skip-worktree paths. So a conflict in a > subdirectory file -- the common case for real series -- still made > git am -3 abort with a clean index: no markers, nothing to resolve. The > user was pointed at a conflict that was not there, git am --continue > dead-ended, and git am --skip silently dropped the patch. Only root-file > conflicts, which the tests happened to use, ever worked. > > git_fetch_am_into_repo now rebuilds a full worktree on a conflict before > handing it back -- abort the partial am, disable sparse-checkout, replay -- > so the conflict is recorded with real markers to resolve. b4 shazam > --resolve and the review TUI both apply through this one function, so both > are fixed, and a regression test drives a subdirectory conflict end to end. > > The same commit hardens the rest of the flow: b4 shazam --abort no longer > crashes on a corrupt state file, --continue refuses up front on a dirty > working tree (keeping its state so it stays re-runnable), a failed > worktree fetch leaves the resolved am in place to retry, and the docs now > note that --continue merges with -M and leaves FETCH_HEAD with -H. > > Signed-off-by: Christian Brauner (Amutable) <[email protected]> > --- v2 will be coming shortly.