StGit maintainer here. I have been a jj user for over a year now. It has proven superior to StGit for all of my workloads. I even use jj when maintaining StGit.
An incomplete list of wins vs StGit includes:
- jj makes managing multiple branches fluid, whereas stg has limited tools for managing patches between stacks. 'stg pick' is largely all there is. It's a real dance to move a patch between stacks.
- jj has a much better system for naming changes. I'm super jealous of how jj solved this problem. StGit requires you to name the patches. I added the feature that allows StGit to refer to patches by relative or absolute index in addition to by name. jj's immutable change ids that can be referenced by unambiguous prefix is the correct answer to this problem.
- 'jj rebase' is so vastly superior to stg push/pop/sink/float for reordering changes that I don't even know where to start. It wasn't immediately obvious to me just how flexible, simple, and powerful 'jj rebase' is when I first started using jj, I have learned that it is in its own league relative to StGit's stack ordering story.
- Similarly 'jj squash' makes 'stg squash' look amateurish.
I could go on. If you're a StGit user, you owe it to yourself to give jj a proper try.
On that first point, there's a use case I sometimes have where stgit feels very clunky:
* I have a branch foo with a stack of patches which are the thing I'm working on, based on a master branch
* I have a separate stack of patches on a branch bar (let's say this is a feature that interacts with foo but it's not ready to upstream yet or maybe at all)
* I want to test and work on the combination of foo and bar and make changes that might need to be updates to some patch in foo, or to some patch in bar
At the moment I pick all the patches in foo onto bar in order to do the work and updates in this combined branch, squashing fixes and changes into appropriate patches. Then once I'm happy I go back to the foo branch, blow away the old patches and re-pick them off my combined branch.
This works but feels super clunky -- does jj do better here? That would be a real incentive to try it out.
For the rest, they don't sound like they're strong enough to beat "I've used stgit for 10 years and have a solid workflow with it".
And I just scanned the jj rebase docs and it looks awful, everything I moved to stgit to get away from. I do not want to think about managing a patch stack in terms of "move a bunch of revisions to a different parent". I like having a straightforward stack of patches that I can push, pop and reorder and list. Don't make me think about graphs of commits and multiple rebase suboptions and all that for something that I do all the time in my main workflow, please.
Combined with jj absorb, some people just work this way all the time, even.
> I like having a straightforward stack of patches that I can push, pop and reorder and list.
You can work this way too, what you'd want is `jj rebase` with -A, -B, and -r: r for the revision, and A and B for the before and after you want to move it too. This lets you reorder things however you want pretty straightforwardly. I tend to work in a stack of patches too, or at least, way more than I used to.
What I mean is that I do not want a single "swiss army knife" rebase command that does everything with lots of options to remember. It's fine to have that in the toolbox for the once in six months weird requirement. But for the simple cases I do every day I want simple commands that each do one thing and have memorable names.
If I'm understanding you correctly, you can have both. If there are specific rebase types that you perform regularly, you can create aliases for them and give them whatever name is meaningful to you.
For example, I frequently use `jj up` to rebase the current branch on main. Likewise, `jj pop` rebases just the current commit (popping it from its current place). I even have a `jj ppop` - better name suggestions are welcome - which does this but for the parent commit.
I suspect that the once-off effort to write your own commands would take no longer than it would take to read the documentation if the commands already existed, but with the hopeful extra benefit of giving you a better understanding of how to use rebase for those once in six months weird requirements when they may arise.
But to be clear, I'm not suggesting you must or even should put in this effort if you have something that works for you. My reply is mostly so that anyone who comes across this discussion and sees Steve's mention of -A, -B, etc isn't scared off by them. Whilst they're always there for you, you can use the power it gives you but in the form of single function commands that don't require you to think.
---
For anyone wondering, the aliases I mentioned. These can be dropped in your jj config with `jj config edit --user`.
Most of the time in jj you don’t even rebase manually, because it’s automatic. And the vast majority of the time, I’m using one or two flags to rebase if I am calling it. You might even need only two in this case (before only might be fine?) I just use both before and after because it’s so easy to remember the names.
Anyway you should use the tools you like, it’s all good.
Obviously `stg push` and `git push` are different commands, but to your point, yes, they have very different meanings and the overlap is somewhat unfortunate.
StGit uses push/pop in the sense of pushing and popping patches to/from the patch stack. An alternative such as apply/unapply would be valid and could be aliased, but this ship sailed 16 years ago (StGit has been around almost as long as Git) and so is unlikely to change.
I removed it because it was challenging to test and maintain, its semantics are somewhat complex, and it wasn't clear that it provided value to anyone.
If you wouldn't mind making your case on the issue tracker [1], I will reconsider the fate of `stg publish`.
I'm not using it any more, but for a while I used stg publish as a way of working with a stack of patches but also providing other people with a "this branch doesn't rebase, you can pull it" interface. It was also nice when working continuously with the same stack of patches (periodically rebasing them onto a moving upstream, cleaning them up, etc) to have the publish view's commits as a record of "this is the delta since the last publish". But it's been years since I had a need for the functionality...
I think I get the gist of what this interactive script does and how you propose to extend it. A PR for such a script to go into StGit's contrib directory would be non-controversial. Maybe a little higher bar to have this capability as a first-class StGit command.
Thank you for the great tool! I gave it my first try today, and immediately fell in love with it! It's a shame I didn't know about it sooner - could have been a great improvement to my workflow.
With the kind of git workflow you describe, bringing StGit into your tooling/workflow may not be worthwhile.
I'd say if you wanted to do these kinds of stack manipulations a little bit faster or with a little less cognitive overhead (e.g. named patches vs SHA1 hashes), then investing in StGit might pay off.
I generally would agree that using StGit isn't going to be a slam-dunk win for someone who already has a capable workflow using interactive git rebase.
Can you explain what your tool does to someone who knows what an interactive rebase is? I don't get much more from your blurb than "we reimplemented interactive rebase for some reason", but I'm sure you do something different or unique...
I originally used mercurial and its queues (mq) extension and then found StGit when switching to an organization using git for version control. Thus I got used to the patch-stack model prior to really being exposed to git's interactive rebase.
Some days I wonder if an interactive rebase oriented workflow would be good enough for me, but manipulating the patch-stack with StGit has become so second-nature that even the small amount of extra friction of `git rebase -i` sends me right back to StGit.
Funny to hear that you learned patch queues with mq. mq was my favorite part of mercurial and it's how I learned to use patch queues too.
Thank you for maintaining StGit — I really enjoy it as a tool! topgit is fine, but quite heavy. I don't use stg much at work with squash merge workflows, but I love it for personal projects or when I need to work on a series of commits with intricate change sequencing.
Probably the main value-add of StGit versus the git-only workflow described is that StGit makes operations on its stack of patches fast and fluid.
Reordering patches with StGit is trivial with `stg push` and `stg pop`. Arbitrary patches can be combined with `stg squash`. A modification in the work tree can be incorporated into the top-most patch with `stg refresh` or an arbitrary patch in the stack with `stg refresh --patch <patchname>`.
In other words, StGit provides a command vocabulary for performing these kind of patch-stack manipulations in a first-class manner.
But as you note, everything StGit does can be accomplished with plain git--albeit with more or less difficulty depending on the particular stack manipulation goal.
A sibling comment mentions interactive rebase. I had never thought about it this way but if stacked got gives you a command vocabulary / imperative interface to adjusting your local commits, I would say `git rebase -i` gives you a declarative interface.
I prefer the latter; it's easier for me to prepare a bunch of modifications in an emacs buffer / vim tab and then have git go and do them all at once rather than try to maintain the state of the commits in my head and plan out the commands one at a time to achieve the same result.
Good point that StGit's docs could benefit from a compare/contrast with interactive rebase workflows. Thanks!
> slightly nicer interface to interactive rebase
More accurate to say StGit is an alternative interface that does some of the same things as interactive rebase (and more). For me, part of StGit's value proposition is that it is not interactive. A single imperative StGit command may accomplish as much as an interactive rebase session.
Workflows using `git rebase --autosquash` feel more similar to StGit because of their non-interactivity.
Describing a patch queue development workflow as a "slightly nicer interface to interactive rebase" does it a tremendous disservice. It's like saying "a database is a slightly nicer interface to a filesystem" — technically true, but a disservice.
You are correct that conflicts can occur when pushing or reordering patches. These conflicts are resolved with the regular git mechanisms. I.e. conflict markers in files, use `git add` to mark conflicts as resolved, and then `stg refresh` to update the patch with conflicts resolved.
I have been running sway on Arch on an XPS13 for the past nine months. As a longtime i3 user, I found the transition as painless as I could have hoped given the bleeding-edge nature of the wayland+sway stack.
A couple of findings from my time with sway:
- It was non-obvious how to tweak keyboard options (I like remapping capslock to ctrl). Various XKB_DEFAULT_* environment variables have to be set before starting sway.
- Firefox used to render poorly due to HiDPI scaling issues. Those seem to have been resolved and FF now works like a champ.
- I was excited about using alacritty as a wayland-native terminal, but it does not yet work with sway. It can be run as an X11 client with sway without issue. Hopefully the wlroots situation helps resolve the remaining issues with alacritty.
- Integer-only display scaling made it somewhat challenging to achieve my sweet-spot for my HiDPI display. I ended up not scaling the display (scale=1) and adjusting various font sizes. I'm happy to see that wlroots will enable fractional display scaling.
> I was excited about using alacritty as a wayland-native terminal, but it does not yet work with sway.
Forgive me if I'm being dense, but: do you mean it's possible for a Wayland app to be incompatible with a particular Wayland window manager (or compositor)? That seems like a huge regression from the X11 status quo.
From what I gather, alacritty and its window system abstraction layers (glutin & winit) are still somewhat immature w.r.t. their wayland support and that sway, due to the limited nature of its wlc layer, do not quite meet in the middle. As stated in TFA, sway is moving toward a more capable wlroots foundation. And the rust-based alacritty ecosystem is also moving forward with tremendous pace. I have little doubt that class of incompatibility will not exist much longer.
Given the newness of not just wayland, but also alacritty, glutin/winit, rust, and sway, I remain astonished that they work as well as they do. But make no mistake, wayland is new tech and thus has some sharp corners where X11 is a well-established quantity after 30 years of existence.
So it does sound like there's a potentially incompatible layer of libraries between application and WM to a degree that isn't really the case with X11, by design. Well, I hope standardization happens quickly. One of the things I like about X11 is how agnostic applications and WMs are to each other, as well as how applications written years and years ago are still compatible with modern X servers.
Yes, this is quite possible..
Wayland is much lower level than X11 so each compositor has to add its own additional protocols which could 'in theory' be incompatible but note that
1) these additional protocols are most of the time a port of the existings protocols
2) the real reason that a Gnome app can run on top of KDE and vice versa is not just because of X11, it's because the developers of the applications and the DE worked together to make it happen so as long as the will is still here the inter-operability will be here eventually.
Eventually is important here because I expect a long instability period..
An incomplete list of wins vs StGit includes:
- jj makes managing multiple branches fluid, whereas stg has limited tools for managing patches between stacks. 'stg pick' is largely all there is. It's a real dance to move a patch between stacks.
- jj has a much better system for naming changes. I'm super jealous of how jj solved this problem. StGit requires you to name the patches. I added the feature that allows StGit to refer to patches by relative or absolute index in addition to by name. jj's immutable change ids that can be referenced by unambiguous prefix is the correct answer to this problem.
- 'jj rebase' is so vastly superior to stg push/pop/sink/float for reordering changes that I don't even know where to start. It wasn't immediately obvious to me just how flexible, simple, and powerful 'jj rebase' is when I first started using jj, I have learned that it is in its own league relative to StGit's stack ordering story.
- Similarly 'jj squash' makes 'stg squash' look amateurish.
I could go on. If you're a StGit user, you owe it to yourself to give jj a proper try.