quilt: Patch Queue Management That Predates Git And Still Outperforms It For Patch Sets

2026-06-05

Before git rebase -i, before git format-patch, kernel hackers and Debian maintainers had a problem: you have a pristine upstream tarball and you need to maintain twenty patches on top of it — patches you'll reorder, refresh against new upstream drops, hand off to colleagues, and ship in a tarball next to the source. quilt solved this in 2003, it still ships in every distro, and it remains the best tool I know for a very specific job: treating a set of patches as a first-class artifact, separate from any VCS.

The mental model is a stack. You push patches onto the working tree, pop them off, refresh them when files change underneath. The patches/ directory holds the actual .patch files plus a series file listing the order.

$ cd linux-6.10/
$ quilt new fix-acpi-quirk.patch     # create new patch on top of stack
$ quilt add drivers/acpi/scan.c      # tell quilt you'll edit this file
$ vim drivers/acpi/scan.c
$ quilt refresh                      # snapshot diff into the patch file
$ quilt new add-debug-knob.patch
$ quilt add kernel/sysctl.c
$ vim kernel/sysctl.c
$ quilt refresh

$ quilt series                        # show the stack
fix-acpi-quirk.patch
add-debug-knob.patch
$ quilt applied                       # what's currently pushed
$ quilt pop -a                        # unwind to pristine tree
$ quilt push fix-acpi-quirk.patch     # reapply just one

The killer feature: quilt refresh regenerates the patch from the current state of the tracked files. Edit, refresh, edit, refresh. No commit ceremony, no rebase. When you want to split a patch, quilt fork clones the top patch and you trim each half by hand. To fold someone else's patch into yours, quilt fold < mbox.

Where this beats git: you receive a new upstream version. With git you'd rebase twenty commits and resolve conflicts inside the rebase machinery. With quilt:

$ quilt pop -a
$ rsync -a --delete ../linux-6.11/ ./
$ quilt push -a                       # apply each patch, stop on conflict
File drivers/acpi/scan.c is read-only; refusing to patch
1 out of 3 hunks FAILED -- rejects in file drivers/acpi/scan.c
Patch fix-acpi-quirk.patch does not apply (enforce with -f)
$ quilt push -f                        # force, leaving .rej files
$ vim drivers/acpi/scan.c             # hand-fix
$ quilt refresh                        # snapshot the resolved version
$ quilt push -a                        # continue

Each patch is a plain unified diff in patches/. You can email them, version them in git (yes, the patches themselves), grep them, hand-edit them. There's no opaque commit graph — what you see in patches/series is exactly what gets applied.

Other commands worth knowing:

When to reach for it: distro packaging, maintaining a long-lived fork that periodically rebases on upstream, prepping a 30-patch kernel series for submission, or any time you want patches as the unit of work rather than commits. It pairs beautifully with git — keep patches/ in git, treat the working tree as throwaway.

Key Takeaway: When patches themselves are the deliverable — distro packaging, upstream submissions, long-lived forks — quilt's pop/push/refresh model is faster and more legible than wrestling git rebase.

All newsletters