"You will be hard-pressed to find someone who stuck with it for a week and decided to go back to git. "
Reporting in. Doesn't mean I will not end up with jj eventually, but so far I always went back to git after a while.
For me it is the staging area and the workflow it allows. Most people hate it and love jj because it does away with it. That is just not me. I don't see the staging area as a hack that was necessary to overcome some superfluous technical limitations but as a workflow tool.
Could I change my ways? Sure. jj just did not provide enough benefit for me so far to do it, but we will see. I am still open to give jj another try some day.
The staging area is a hack in that it is its own unique concept that doesn't work with any of the rest of git's tooling without needing special, inconsistent flags for commands to target it (git stash, git reset, etc.).
I use a staging area with jj! I would surmise most jj users do too. It's just a real, honest-to-god commit in the repo instead of a special snowflake.
# do some work
…
# prepare a new, empty commit if you don't already have one
jj new --no-edit --insert-before @
# move changes into it; repeat ad nauseam
jj squash --interactive
Since it's just a commit, all your tools work with it out of the box. And you don't need to stash changes when you jump around between branches.
Yeah, I regularly have MANY "staging commits" at the same time in jj, in which I just throw ideas in that I don't want to pollute or yet know how to integrate with the other ideas. I use squash, split, interactive split, rebase etc to move lines and changes around etc...
When I eventually figure it all out, I can tidy it all up into completely coherent, discrete, sequential commits that make it look like I knew exactly what I was doing from the start, then push to remote.
Conversely git staging around stashing was always an absolute, terrifying mystery to me. I could never remember what was stored where, and would consequently end up losing work, repeating work, and, most of all, just making massive commits that make no sense.
I was sold on jj from essentially the moment I found it, but I remain routinely amazed at how much more powerful (yet simple!) it is than I realized.
In my mind, in some sense, every commit can simultaneously be a stash, staging area, part of a branch and more. Because you can easily create endless branches on top of, beside, before, as merges of, etc.. any commit. And it all automatically rebases, conflicts often auto-resolve (or at least don't block you immediately).
I really don't know how to best describe it. But there's a reason that many people are quite literally evangelizing it in every post that comes up - who does this for git, or anything?
Just give it a try. And, even better, use it via jjui
The commit message is the least useful part of all of this.
It is just SO EASY to move, merge, split, rebase, squash etc commits, and even just individual lines and sections from within commits (via split).
And it's all even easier via jjui
I don't think there's anything any of us can really say to convince those of you who are constitutionally skeptical about it (or even allergic to it) why you should try it... If all of our fawning and evangelizing isn't enough to get you to at least give it a fair shake, then there isn't much else to be said.
It's just that I'm fine and also the features seam to amount only to a change in usage not in actual new features. In this case if you want to use commits instead of a stash, then you can do that just fine in git.
It's also that I want my commit hashes to be stable (because I cross-reference them) and it sounds like they wouldn't in jj, because it is kind of rebase-y?
Commits in jj have both a commit has (which is unstable) and a commit id (which is not).
Generally you use the id, not the hash.
And yes, everything you can do with jj you can also do with git. It’s just that most people don’t, because it’s much harder with git, involves rebases and changing hashes, and so on.
I would call `jj absorb` a new feature (new if coming from git, I believe the idea was taken from hg). It moves diffs into the closest ancestor that touched those files/lines. Very useful for addressing reviews, then just `jj absorb` and watch them get squashed into the correct location.
This gets even better with octopus merges (known in the jj community as "megamerges"): open up 5 branches at the same time, address minor tweaks in any number of them, and `jj absorb` the content into the right parent branch.
It does not, or at least not very well. Merges can't be rebased without replaying conflict resolution; since Git lacks a first-class concept of conflicts, that becomes a manual process.
Moreover, jj should be able (I haven't explicitly tried this) to autogenerate the conflict resolution in the `jj absorb` case, since it knows what the final post-merge state should be.
It's the new workflows that it enables via making existing features vastly more accessible (though there are some new features, such as merge conflicts not being a showstopper).
Can you edit commits by adding on only parts of your "staging" area?
Because that's my workflow. I produce a few focused and semantically coherent commits that I'd like to apply to the codebase, where each keeps the codebase in a working state. I might be working on more than one thing at once, but I know which commit each set of changes should "live in."
An append-only log of commits is decidedly not something I want. Is jj amenable to this?
Extremely amenable—my workflow shifted to match your description after I started using jj, because it makes that easier. Conceptually, it’s not “edit commits by adding on only parts of your staging area”, but “edit commits by only moving or splitting parts from another commit”, and since the working copy is a commit, it is handled by that general case instead of being it’s own thing.
jj squash allows you to move changes from a revision to another. Default is your working copy, but there's nothing preventing you from working on several semantic commits and moving changes from your working copy to those commits as you want.
jj squash --into -r <revset>
Where <revset> is @-, a change id, or perhaps a bookmark name if you want to give a semantic name to your changes.
Thanks for the clear and concise summary. It is helpful for some workflows.
For me the staging area being a snowflake is the feature. It is a special temporary singleton commit if you will, but I can rely on its temporary and singleton nature. As that it should have a different interface from regular commits.
I found it hard to stick to due to pre-existing workflows too. I find I'm often switching between branches in git, and our CI depends on pushing to specific branches - I constantly found myself a bit lost with jj about which underlying branch I was on and where that would get pushed to. I did Steve's tutorial and came out of that really liking the concepts, but still unable to map it all in my head when it came to pushing my work to a remote.
On the other hand, tools like jj seem great for people who spend a lot of time refining and perfecting every commit so that their repo history is pristine. I’m not one of those people. My git hygiene is atrocious. I have git halitosis. But functionally, it’s fine. Everything is in the git history and is recoverable. That’s about all I care about.
Also, I don’t have the capacity to juggle a lot in my mind. If someone does, then sure, jj may facilitate that. But I don’t need such facilitation.
Jujutsu might look like it's for people who want to perfect their commits and juggle a lot in their minds -- but in my case (and anecdotally in others' too) it's because it lets us easily do things which would require that mindset/ability with plain Git.
In Git, I need to keep in mind all the different things I'm working on and which branch goes where, or I wind up with a monster PR with a chain of commits that mix everything up enough that it's even more effort to pull the PR apart to be reviewable. Ask my colleagues how I know that :P.
With jj, I don't feel that I'm putting more effort into organising my changes -- quite the opposite -- not least because there's very little book-keeping involved in parking something that's in progress or coming back to it later. And when I come to ask for a review, I've got separate changes I can push as smaller PRs, and I can easily pull the right sets of changes out to make each one reviewable.
I think the biggest improvement is that if I just need to look at something else for a couple of minutes then come back, I can `jj new main` to switch and not bring my changes with me then I can `jj edit <oldref>` to get my working copy back into the state it was in before, with all my old changes.
I'm pretty sure none of my colleagues have started using it (although they're free to) but I can confidently say (because I've asked) that they've noticed the difference in my work and prefer the more focused changes.
Reporting in. Doesn't mean I will not end up with jj eventually, but so far I always went back to git after a while.
For me it is the staging area and the workflow it allows. Most people hate it and love jj because it does away with it. That is just not me. I don't see the staging area as a hack that was necessary to overcome some superfluous technical limitations but as a workflow tool.
Could I change my ways? Sure. jj just did not provide enough benefit for me so far to do it, but we will see. I am still open to give jj another try some day.