Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

The whole patch quilting thing is awful. Just keep the patches as commits. It won't "trick" me or anyone else, especially if you keep them in branches that denote "debian".

Please, please, stop the nonsense with the patch quilting -- it's really cumbersome, it adds unnecessary cognitive load, it raises the bar to contributions, it makes maintenance harder, and it adds _zero value_. Patch quilting is a lose-lose proposition.





> The whole patch quilting thing is awful. Just keep the patches as commits.

I'd say that `quilt` the utility is pretty much abandoned at this point. The name `quilt` remains in the format name, but otherwise is not relevant.

Nowadays people that maintain patches do it via `gbp-pq` (the "patch queue" subcommand of the badly named `git-buildpackage` software). `gbp-pq switch` reads the patches stored in `debian/patches/`, creates an ephemeral branch on top of the HEAD, and replays them there. Any change done to this branch (new commits, removed comments, amended commits) are transformed by `gbp-pq export` into a valid set of patches that replaces `debian/patches/`.

This mechanism introduces two extra commands (one to "enter" and one to "exit" the patch-applied view) but it allows Debian to easily maintain a mergeable Git repo with floating patches on top of the upstream sources. That's impossible to do with plain Git and needs extra tools or special workflows even outside of Debian.


> That's impossible to do with plain Git and needs extra tools or special workflows even outside of Debian

Rebase.


Also rebasing has less information available to it, so it's less likely to update cleanly than merging. Don't do it!! Just consider the diff between the new head and upstream as "the diff" and describe the reasons for it.

What, no. In a merge you have two parents and their histories. In a rebase you have... the same thing as-if you had merged a fast-forward-ready branch. It's the same thing.

If you insist you can add Merge commits to bracket fast-forward pushes, but arguably there is no need, and especially so for something like Debian packages where the convention would be that Debian's patches are "always on top", so you can see them by doing `git log ${base}..${debian_release_branch}` for any release. (And what's the base? Whatever upstream branch/tag the Debian release is based on, but you can add more tags with a Debian naming convention to denote the bases.)


In practical, large-scale usage, the default merging algorithm works better than the default rebase algorithm. But I did switch teams from using a rebase workflow to a merge workflow and manual conflict resolution needs went way, way down. Obviously there are confounding issues, but that's my experience.

If your patches never touch the same files as others, I think it doesn't matter. But, IIRC, if patch A and patch B both touch file F, and the changes in patch A are in context for diffs of patch B, it always fails if patch A changes patch B's context, but since merging incorporates all changes at once, these separate context changes don't apply.

It's been a while, but it might be only when you need to manually resolve patch A, then you also have to manually resolve patch B even if you wouldn't have had to touch it in a merge scenario.


> In practical, large-scale usage, the default merging algorithm works better than the default rebase algorithm.

You're referring to having to do conflict resolution for each commit in the rebase series, as opposed to all at once for a merge. Either way if the upstream has added thousands of commits since the last time, you're in for no fun.

This is a case where Git could be better, but as I responded to u/gioele there exist tools that greatly help with the conflict resolution issue, such as this one that I wrote myself:

https://gist.github.com/nicowilliams/ea2fa2b445c2db50d2ee650...

which basically bisects to find the upstream commit that introduces a conflict with each commit in the rebase series.

This has one major advantage over merge workflow conflict resolution: you get the most post possible context for each manual conflict resolution you have to do! And you still get to have clean, linear history when you're done.


What siblings say. What you want is `git rebase`, especially with the `--onto` and `--interactive` options. You might also want something like bisect-rebase.sh[0], though there are several other things like it now.

[0] https://gist.github.com/nicowilliams/ea2fa2b445c2db50d2ee650...


Rebasing would mean there's no continuous versioning of the "patches on top", which might be undesirable. Also, the history rewriting might make cooperation difficult.

Merges would avoid those problems, but are harder to do if there are lots of conflicts, as you can't fix conflicts patch by patch.

Perhaps a workflow based on merges-of-rebases or rebase-and-overwrite-merge would work, but I don't think it's fair to say "oh just rebase".


> Rebasing would mean there's no continuous versioning of the "patches on top", which might be undesirable. Also, the history rewriting might make cooperation difficult.

Let's say you have these version tags upstream: foo-1.0.1, foo-1.1.0, foo-1.3.0, and corresponding Debian releases 1.0.1-0, 1.1.0-0, 1.1.0-1, 1.3.0-0, 1.3.0-1, and 1.3.0-2, and the same 3 patches in all cases, except slightly different in each case. Then to see the several different versions of these patches you'd just `git log --oneline foo-${version}..debian-${version}-${deb_version}`.


Gerrit introduces the concept of Commit-Id; essentially a uuid ties to the first review which merged a proposed commit into the trunk.

Cherry picks preserve that Commit-Id. And so do rebases; because they're just text in a commit message.

So you can track history of patches that way, if you needed to. Which you won't.

(PS some team at google didn't understand git or their true requirements, so they wasted SWE-decades at that point on some rebasing bullshit; I was at least able to help them make it slightly less bad and prevent other teams from copying it)


But that Commit-Id footer has no functional effect. I don't see how it would help me if I have a clone of the repo, and my upstream (in this case, the debian maintainer) rebases.

> Which you won't.

Why not? Doesn't it make sense to be able to track the history of what patches have been applied for a debian package?


You need additional tooling to make use of Commit-Id. With Gerrit, it does link them all together.

> Doesn't it make sense to be able to track the history of what patches have been applied for a debian package?

... no. Each patch has a purpose, which will be described in the commit message. Hopefully it does what it says it does, which you can compare with its current diff.

If it was upstreamed with minimal changes, then the diff is near-empty. Drop it.

If it was upstreamed with significant changes, then the diff will be highly redundant. Drop it.

If the diff appears to do what the commit message says it does, then it probably does what it says.

If the diff is empty, either it was upstreamed or you fucked up rebasing. Don't be negligent when rebasing.


How is that not literally the git history?

It is, except after rebasing.

That’s what git-rebase is for, and it is built into standard git.

Maintaining separate upstream sources and downstream patches does provide value. Maybe not to you, but it does.

For example, it's trivial from a web browser with a couple of clicks to go and find out all the downstream changes to a package. For example to see how glibc is currently customized in debian testing/unstable you can just navigate this webpage:

https://sources.debian.org/src/glibc/2.42-6/debian/patches

If everything gets merged in the same git tree it's way harder. Harder but doable with a rebase+force push workflow, which makes collaboration way harder. Just impossible with a merge workflow.

As an upstream maintainer of several project, being able to tell at a glance and with a few clicks how one of my projects is patched in a distribution is immensely useful when bug reports are opened.

In a past job it also literally saved a ton of money because we could show legal how various upstreams were customized by providing the content of a few .debian.tar.gz tarballs with a few small, detached patches that could be analyzed, instead of massive upstream trees that would take orders of magnitude more time to go through.


> For example, it's trivial from a web browser with a couple of clicks to go and find out all the downstream changes to a package.

How is this not also true for Git? Just put all the Debian commits "on top" and use an appropriate naming convention for your branches and tags.

> If everything gets merged in the same git tree it's way harder.

Yes, so don't merge, just rebase.

> Harder but doable with a rebase+force push workflow, which makes collaboration way harder.

No force pushes, just use new branch/tag names for new releases.

> Just impossible with a merge workflow.

Not impossible but dumb. Don't use merge workflows!

> As an upstream maintainer of several project, being able to tell at a glance and with a few clicks how one of my projects is patched in a distribution is immensely useful when bug reports are opened.

Git with a suitable web front-end gives you exactly that.

> In a past job it also literally saved a ton of money because we could show legal how various upstreams were customized by providing the content of a few .debian.tar.gz tarballs with a few small, detached patches that could be analyzed, instead of massive upstream trees that would take orders of magnitude more time to go through.

`git format-patch` and related can do the moral equivalent.


Moving from a patch stack maintained by quilt to git is what this article is about.

It's worth mentioning the quilting approach likely predates the advent of git by at least a decade.. I think compatibility with git has been available for a while now and I assume there was always something more pressing than migrating the base stack to git

dgit handles the whole affair with very little fuss I've found and is quite a pleasant workflow.

What is dgit?


Thanks! IMO Debian should just switch to only Git.

What is patch quilting, for the blissfully unaware?

https://wiki.debian.org/UsingQuilt but the short form is that you keep the original sources untouched, then as part of building the package, you apply everything in a `debian/patches` directory, do the build, and then revert them. Sort of an extreme version of "clearly labelled changes" - but tedious to work with since you need to apply, change and test, then stuff the changes back into diff form (the quilt tool uses a push/pop mechanism, so this isn't entirely mad.)

Ha yes that does sound mad. If only there was a version control system specifically designed to track changes to code...

Quilt predates Git. Back then source was distributed as a tarball, and Debian simply maintained a directory full of patches to apply to the tarball.

Sure but Git has been available (and super popular) for almost 20 years now.

Yea, so? Debian goes back 32 or more years, and quilt dates to approximately the same time. It’s probably just a year or two younger than Debian.

At Mozilla some developers used quilt for local development back when the Mozilla Suite source code was kept in a CVS repository. CVS had terrible support for branches. Creating a branch required writing to each individual ,v file on the server (and there was one for every file that had existed in the repository, plus more for the ones that had been deleted). It was so slow that it basically prevented anyone from committing anything for hours while it happened (because otherwise the branch wouldn’t necessarily get a consistent set of versions across the commit), so feature branches were effectively impossible. Instead, some developers used quilt to make stacks of patches that they shared amongst their group when they were working on larger features.

Personally I didn’t really see the benefit back then. I was only just starting my career, fresh out of university, and hadn’t actually worked on any features large enough to require months of work, multiple rounds of review, or even multiple smaller commits that you would rebase and apply fixups to. All I could see back then were the hoops that those guys were jumping through. The hoops were real, but so were the benefits.


> Yea, so?

So it's clearly a way better solution and it's disappointing that they still haven't switched to it after 20 years? I dunno what else to say...


So has git-buildpackage; the debian historical archives don't go further back than v0.4, but the oldest bug report referencing gbp is from december 2006: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=403987

it's quite difficult to maintain a quilt like workflow with plain git

I've tried it


Quilt is difficult to maintain, but a quilt-like workflow? Easy: it's just a branch with all patches as commits. You can re-apply those to new releases of the upstream by using `git rebase --onto $new_upstream_commit_tag_or_branch`.

How do you track changes to the patches themselves?

By having a naming convention for your tags and branches, then you can always identify the upstream "base" upon which the Debian "patches" are based, and then you can trivially use `git log` to list them.

Really, Git has a solution to this. If you insist that it doesn't without looking, you'll just keep re-inventing the wheel badly.


but then if I want to see the history for a specific patch, or bisect them?

mercurial has a patch queue extension that married it and quilt, which was very easy to use


Do you ever really want this? I don't recall wanting this. But you can still get this: just list the ${base_ref}..${deb_ref} commit ranges, select the commit you want, and diff the `git show` of the selected commits. It helps here to keep the commit synopsis the same.

E.g.,

  c0=$(git log --oneline ${base_ref0}..${deb_ref0} |
         grep "^[^ ] The subject in question" |
         cut -d' ' -f1)
  c1=$(git log --oneline ${base_ref1}..${deb_ref1} |
         grep "^[^ ] The subject in question" |
         cut -d' ' -f1)
  if [[ -z $c0 || -z $c1 ]]; then
    echo "Error: commits not found"
  else
    diff -ubw <(git show $c0) <(git show c1)
  fi
See also the above commentary about Gerrit and commit IDs.

(Honestly I don't need commit IDs. What happens if I eventually split a commit in a patch series into two? Which one, if either, gets the old commit ID? So I just don't bother.)


So there’s no way to have commit messages on changes to patches? There’s also https://dep-team.pages.debian.net/deps/dep3/

People keep saying “just use Git commits” without understanding the advantages of the Quilt approach. There are tools to keep patches as Git commits that solve this, but “just Git commits” do not.


Having maintained private versions of Debian packages, I have zero need for "commit messages on changes to patches". I can diff them as needed as I showed, but I rarely ever need to -- I mostly only rebase onto new upstreams. Seeing differences in patches isn't helpful because there is not enough context there as to what changed in the upstreams.

I rather suspect that "commit messages on changes to patches" is what Debian ended up with and back-justifies it.

Of course, I am not a Debian maintainer, so it's entirely possible I'm just missing the experience of it that would make me want "commit messages on changes to patches".


Quilt was AFAIK used before Git, so you’re not wrong. But now that it’s there, it has some advantages.

I’m not arguing against replacing Quilt, but it should be more than just Git. I haven’t done Debian packaging in a long time but apparently there are some Git-based tools now?


I don't know that I've ever wanted to diff a diff, but you could do that still. And bisecting would still be possible, especially if you use merges instead of rebases.

Bisect rebases... you mean that you have two release branches based on divergent upstream branches and you want to quickly test where a bug was introduced on the way from the one to the other? What I would do in a rebase workflow is find the merge base (`git merge-base`) of the two release branches, and bisect from that to the release branch I'm interested in.

You can keep the old branches around if you want. Or merge instead of rebasing.

Those who don't understand git are doomed to reimplement half of it poorly?

(I know that's not quite the Greenspun quote)


I think that's right, sadly.

> 4. No-one should have to learn about Debian Source Packages, which are bizarre, and have been obsoleted by modern version control.



Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: