Been using jj at work for months now. In colocated mode, JetBrains IDEs even retain some if their VCS integration.
The ability to easily work on top of an octopus merge and then push changes "down" into the contributing branches has been a live saver when my team had to do a big refactoring in a mono repo and split the changes into small PRs for individual teams (code owners).
The auto committing behavior is a bit weird at first, but now I don't want to go back to git. It feels a bit like the step from SVN to git back in the the day. ("this feels weird" -> "how did people ever tolerate the old way?")
Full agreement on both “it feels weird” -> “how do people ever tolerate the old way” as well as the auto commit behavior being one of those things. In fact I probably over-index on that specifically when talking about jj. I thought I’d hate this because I love git’s index. Turns out that by getting rid of the index, jj has a better index than git does, but that sounds insane at first!
Same about the index! I initially skipped over jj thinking the lack of an index was a huge step backwards but commit-splitting is a massive improvement.
I do wish there was a better front end for it though.
100% agreement on that transition. I feel like I had to unlearn a lot of git’s subtly-broken model and now things feel so much simpler and easier.
One of those for me was branch names that don’t automatically “follow” new commits. At first it felt weird but it unlocks the ability to do consecutive work as one linear set of changes, even when those changes need to be merged in discrete chunks. The git approach for this (stacking branches) is so painful, particularly when you need to edit an earlier change or add a new commit between earlier ones. This went from being so frustratingly difficult I wouldn’t even consider it to being utterly trivial.
Also rebase conflicts. Not being unceremoniously dropped into a half-broken “fix this NOW state” with no ability to inspect and poke at other commits in the chain and not being able to fix things incrementally in any order is something I couldn’t have imagined. And like you said now it’s insane to me that people continue to put up with it.
To me at least it makes so much more sense to be like:
1. I am going to work on $X
2. autocommit
3. My work on $X is done
rather than
1. I make changes
2. I am done making changes
3. Now I have to describe what I changed and how
Maybe this is just me, but with git it is at times hard at times to hit the right balance in terms of commit granularity — and for my flow planning forward ("I am gonna do $X") rather than describing what I did ("I did $X") seems more.. focused?
It's a bit of a magic trick. A "snapshot" is taken any time a command is run, and it happens implicitly before any actual algorithms or code for a given command is run (massively simplifying the internal design), so for all intents and purposes it's "automatic" from the user interface e.g. even checking repo status or otherwise small operations will cause a snapshot.
But you can integrate with https://github.com/facebook/watchman/ in order to have a truly daemon-ified option where any filesystem write will cause a snapshot to be taken.
> I also heard friends rave about "stacked diffs" but struggled to understand what exactly was going on there. Nothing I read or conversations I had have clicked.
I wonder what it is about descriptions of stacked diffs that doesn't land - it's literally just a rebase-centric workflow instead of the merge-centric workflow popularised by GitHub et al.
For me, my git brain is very low level. And none of them ever explains what actually happens under the hood, or how that was different than branching…
With some respect, I think “rebase centric workflow” doesn’t really cover it: I use rebasing heavily with GitHub. A “trunk based development where all branches are rebased before merge so there’s never merge commits, please add to commits and rebase the branches in response to review comments” development style is still very rebase centric, but not stacked.
You also have to remember (though there’s no reason you should know this) that GitHub came out of the community I was heavily involved in at the time of its birth. I’ve been using GitHub for longer than most people, and so the PR-style workflow has been the air I’ve breathed for so long, it can be hard to understand other things at first. I had used subversion before git, but didn’t really understand much about it.
Anyway, that’s just a roundabout way of saying that I think this space is super interesting because these tools are so flexible that they can be used in so many different ways, and it’s easy to assume that “how you use git” is some sort of shared experience when that’s not really true.
What I find confusing with people raving about it as something different is the considering the following scenario:
refactor/a # should be merged as independent PR
feature/a-b # depends on a; should be merged independently, after
fix/c # independent
Then I will probably have some local `dev` branch checked out with a combination of all of the above and maybe some.
How else than "stacked diffs" would you submit all of this for review concurrently while still working on all of them? It sounds like a new word for what we were always expected to do? What's an alternative which doesn't rely on compromising merge-strategy?
At this point I'm suspecting "stacked diffs" is just a crotch for people still barely coping with DVCS but I could be missing something.
Yeah, and I think it's also worth noting that by far the largest set of folks advocating for stacked diffs are not actually using git.
Meta runs a custom mercurial-compatible monorepo that was scaled up to handle thousands of commits per hour, and they have a culture of constant codebase-wide refactoring commits (i.e. the ongoing live migration of PHP -> Hack) - that rate of change causes problems that most GitHub projects have no reason to solve.
The holy grail of a stacked diff workflow would be making multiple Github PRs each made against the previous branch instead of trunk, and then updating the branch that's closest to trunk and rebasing all of the children PRs without having to force push into any of them.
Git and Github do not support this workflow directly, and this creates space for all the other tools.
Jujutsu comes close to supporting this workflow directly, without having to provide any specialized utilities that mention "stacked diffs" at all.
https://github.com/spacedentist/spr (not to be confused with ejoffe/spr) is a utility that maps a local change to a remote branch, updating the branch (without force pushes) when the local change is updated. (Changes work the same as they do in JJ, but the implementation is different.) And this works even when you have a stack of changes and update one in the middle of the stack.
Maybe the problem here is that there aren't any open tools implementing the user experience, because I'd say it's exactly the opposite - that it is implemented using rebase under the hood is entirely secondary to the user experience of "stacking" changes on top of one another.
Steve, I see you’re in this thread. I was using jj for a while before reading your tutorial and yet still found it quite insightful and helpful. Thanks for your contribution!
I am torn between sapling and jj. Both make good progress in git/github integration which seems to have been the major road block in adoption before. One other major roadblock seems to be the limits of review tools supporting stacks: github PRs are too limited, gerrits ux is horrible, graphite does not work and is not open enough, saplings review tool is just a very slow performing POC (though with a really good UI concept as starting point)
for me important argument in favour of JJ over Sapling was "first-class conflicts" - JJ stores conflicts in the history and allows you to resolve them later, while Sapling forces you to resolve conflicts at the point when they happen
If first class resolution is done right, then instead of project generators we can just create sample projects that people fork, and when you make breaking changes or add new startup config to the project, you update the sample project(s) and people can pull the updates. Once you resolve the conflicts you’re done until the next change, at which point your repo remembers how the last conflict was resolved, and doesn’t ask you to redo it.
This is why jj is on my todo list. I’m not calling it jujutsu no matter how much someone pays me though.
Gerrit, as I like to say, has a user interface that only a mother could love. But ultimately it's a very productive tool, so I just got over it. I even wrote some integration between jj and gerrit, making submitting stacks very easy and smooth.
IMO, Gerrit is the best currently available option by a large margin, notwithstanding its quirks.
graphite only works with graphite tooling. you cannot just use sapling or jj to create a pr on github and then use graphites review tool, even though this should work in theory, but they block this somewhere in the pipeline.
One of my favorite people talking about my single favorite tool of the past 3+ years. Up there with (above, really) zellij and helix for changing my daily life.
Zellij looks powerful but also a bit too complex, following the "kitchen sink" school of design :-). No biggie but its name is too close to IntelliJ imho. What kind of workflow do you use with it?
I used tmux a bit back in the day, but these days I feel like good old tabs and app windows cover my needs. When I want to multiplex processes in a single window, I reach for Overmind. [1]
I don't know what you find complex about Zellij, as I haven't used it extensively, but the few times I've used it, the UI was eminently self-describing, I managed to do everything I've needed to do within a minute of first launching it.
Is there more advanced stuff that's more complex that I just haven't seen?
Not the OP, but Helix is a minimal fuss modal editor with sensible defaults. My config is maybe five lines? I say "maybe" because I haven't looked at it I first wrote it. And I think I'd probably be just fine with no config.
nice to see zellij+helix combo users out there. Helix been my fav editor for like a year already, zellij is also a daily driver, and now i'm learning jj :P
Love it, read a couple of chapters already and planning to finish the rest. As a person completely new to jj and someone who also enjoys git CLI, this is an intuitive, very useful and enjoyable read.
I’m especially interested after learning about the git compatible backend:
> There's one other reason you should be interested in giving jj a try: it has a git compatible backend, and so you can use jj on your own, without anyone else you're working with to convert too.
The ability to easily work on top of an octopus merge and then push changes "down" into the contributing branches has been a live saver when my team had to do a big refactoring in a mono repo and split the changes into small PRs for individual teams (code owners).
The auto committing behavior is a bit weird at first, but now I don't want to go back to git. It feels a bit like the step from SVN to git back in the the day. ("this feels weird" -> "how did people ever tolerate the old way?")
I do wish there was a better front end for it though.
One of those for me was branch names that don’t automatically “follow” new commits. At first it felt weird but it unlocks the ability to do consecutive work as one linear set of changes, even when those changes need to be merged in discrete chunks. The git approach for this (stacking branches) is so painful, particularly when you need to edit an earlier change or add a new commit between earlier ones. This went from being so frustratingly difficult I wouldn’t even consider it to being utterly trivial.
Also rebase conflicts. Not being unceremoniously dropped into a half-broken “fix this NOW state” with no ability to inspect and poke at other commits in the chain and not being able to fix things incrementally in any order is something I couldn’t have imagined. And like you said now it’s insane to me that people continue to put up with it.
1. I am going to work on $X
2. autocommit
3. My work on $X is done
rather than
1. I make changes
2. I am done making changes
3. Now I have to describe what I changed and how
Maybe this is just me, but with git it is at times hard at times to hit the right balance in terms of commit granularity — and for my flow planning forward ("I am gonna do $X") rather than describing what I did ("I did $X") seems more.. focused?
I am a bit skeptical about this, because this requires a jj daemon?
But you can integrate with https://github.com/facebook/watchman/ in order to have a truly daemon-ified option where any filesystem write will cause a snapshot to be taken.
I haven't checked the source.
I wonder what it is about descriptions of stacked diffs that doesn't land - it's literally just a rebase-centric workflow instead of the merge-centric workflow popularised by GitHub et al.
With some respect, I think “rebase centric workflow” doesn’t really cover it: I use rebasing heavily with GitHub. A “trunk based development where all branches are rebased before merge so there’s never merge commits, please add to commits and rebase the branches in response to review comments” development style is still very rebase centric, but not stacked.
You also have to remember (though there’s no reason you should know this) that GitHub came out of the community I was heavily involved in at the time of its birth. I’ve been using GitHub for longer than most people, and so the PR-style workflow has been the air I’ve breathed for so long, it can be hard to understand other things at first. I had used subversion before git, but didn’t really understand much about it.
Anyway, that’s just a roundabout way of saying that I think this space is super interesting because these tools are so flexible that they can be used in so many different ways, and it’s easy to assume that “how you use git” is some sort of shared experience when that’s not really true.
How else than "stacked diffs" would you submit all of this for review concurrently while still working on all of them? It sounds like a new word for what we were always expected to do? What's an alternative which doesn't rely on compromising merge-strategy?
At this point I'm suspecting "stacked diffs" is just a crotch for people still barely coping with DVCS but I could be missing something.
Meta runs a custom mercurial-compatible monorepo that was scaled up to handle thousands of commits per hour, and they have a culture of constant codebase-wide refactoring commits (i.e. the ongoing live migration of PHP -> Hack) - that rate of change causes problems that most GitHub projects have no reason to solve.
Git and Github do not support this workflow directly, and this creates space for all the other tools.
Jujutsu comes close to supporting this workflow directly, without having to provide any specialized utilities that mention "stacked diffs" at all.
https://github.com/spacedentist/spr (not to be confused with ejoffe/spr) is a utility that maps a local change to a remote branch, updating the branch (without force pushes) when the local change is updated. (Changes work the same as they do in JJ, but the implementation is different.) And this works even when you have a stack of changes and update one in the middle of the stack.
https://martinvonz.github.io/jj/latest/sapling-comparison/
This is why jj is on my todo list. I’m not calling it jujutsu no matter how much someone pays me though.
IMO, Gerrit is the best currently available option by a large margin, notwithstanding its quirks.
And yeah, the lack of good review tooling is certainly a big issue.
Zellij looks powerful but also a bit too complex, following the "kitchen sink" school of design :-). No biggie but its name is too close to IntelliJ imho. What kind of workflow do you use with it?
I used tmux a bit back in the day, but these days I feel like good old tabs and app windows cover my needs. When I want to multiplex processes in a single window, I reach for Overmind. [1]
--
1: https://github.com/DarthSim/overmind
Is there more advanced stuff that's more complex that I just haven't seen?
I’m especially interested after learning about the git compatible backend:
> There's one other reason you should be interested in giving jj a try: it has a git compatible backend, and so you can use jj on your own, without anyone else you're working with to convert too.
I even started writing one but that was a pretty big project and I lost the motivation for it.