Guilt is pretty cool. I’m talking about the set of scripts to manage patch queues on top of a git branch, of course. Oh, you haven’t heard of it? Well, let me tell you all about it!
In this post I’m going to assume you know what git is and how to use it. If you don’t, let me know and I might write an “intro to git” article. Maybe I’ll write it even if nobody asks for it, we’ll see.
If you’re not familiar with patches, it’s basically what git diff
outputs:
|
|
In other words, it’s just some file that describes changes in some other files. This makes it simple to distribute and apply arbitrary changes to source code. Of course, it’s possible for a given patch to be inapplicable to your current version of the source code, and in that case you end up with something similar to a git merge conflict. But this is just the nature of these things. A tool that would allow you to avoid such conflicts completely probably lies in the domain of science fiction.
The main idea of guilt is to allow users to store their commits as patch files. This provides the following benefits:
The user can easily go both up and down the commit history. This is because guilt remembers a list of patches that you can “push” on and “pop” off the “currently applied” patch stack. Since this list is also stored as a text file, you can edit it and reorder patches as you wish (just make sure they are still applicable in the new order).
Patches are just text files too and therefore can be edited using standard tools like sed, awk, all kinds of editors and so on. Renaming things, removing changes (hunks) or moving them between patches becomes trivial. This is not a very stable procedure, of course, since you can invalidate your patches quite easily. However, there is a huge class of actions that can be done safely enough and it can often be less annoying than resolving conflicts.
If you’re particularly clever, you can even turn your patch directory into a git repository and track your “metachanges”. I’ve never done this myself but I’m starting to think about trying that out someday.
Guilt provides a very nice quality of life improvement: every patch can be
assigned a set of “guards”, which lets the user avoid applying the patch
unless they explicitly request it. Say you’ve got some debug patch that makes
your program print some diagnostics info, making it slower and polluting its
logs. By giving this patch a +debug
guard, you ensure that it will be
applied only if you enable the debug
guard.
Using this feature lets you easily switch between multiple versions of your code base, similarly to git branches. But these branches differ only in particular commits, while keeping everything else shared and easily updatable. Whether you should do things this way is a separate question, of course.
Of course, all of the above is possible with just plain git. However, guilt makes it all so much easier.
Everything I’ve written above applies to the last release of guilt. There were some features I wanted it to have, so I started my own fork. The original author has abandoned guilt quite some time ago (more than 5 years at the time of this writing), so all we have now is forks.
So far I’ve implemented some small quality of life improvements and one rather large feature: patch splitting. The idea is to allow the user to take some patch and split it into multiple ones based on some logic. The user can manually select the changes or rely on some rules, e.g. “move changes in different files to different patches”.
This feature enables a workflow where you do everything in one patch and then clean it up and turn it into a proper patch series before submitting it upstream or pushing to your repository. It may sound like extra effort, but it’s not always possible to plan ahead, especially when you’re not intimately familiar with the code base. You can look at the code all you want, but it’s very likely that you won’t have much progress until you start experimenting with the code. At some point one of these experiments will turn out to be what you need, and then you just need to clean up. That’s where this feature shines.
There is a lot more that can be said about patch splitting. e.g. how to set it up. I’m afraid, the process is a little bit involved right now, so I’ll leave this subject to another article.
The story of my fork doesn’t end here, though. I’ve got many more ideas I hope to implement at some point, so stay tuned!