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.
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.
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.
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]
--
Is there more advanced stuff that's more complex that I just haven't seen?
> Helix, the editor? How would you pitch it?
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.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.
From a tiny bit of previous jj experience, my mental model is "a commit is the snapshot, and a change is what happened between snapshots", but that might be wrong. It would be great if this could be clarified a bit more in the tutorial.
As you iterate on one change, new underlying git commits are made to snapshot the latest state of the current change being edited. The change ID remains stable though the backing commit ID varies as the change’s contents are modified.
You can always revert a change back to a previous backing commit.
This has a few cool implications.
First, you never have uncommitted changes. You are always editing a “current” change with an ID that is regularly persisting your work (either every time you run a jj command or with a filesystem event monitor).
Second, you’re never “on” a named branch: you’re only ever “on” a change and named branches are just mutable pointers to change IDs. This is awesome for a long-lived linear bit of work that needs to be merged in piecemeal. In git you’d need multiple branches based on one another and nothing tracks the relationship between them. Updating earlier work is painful. With jj, it’s all just one linear branch with some changes having names. If you need to edit an earlier change or insert new ones, you just… do that.
I should probably use jj at this stage and figure all this out for myself, rather than just read about it. Thank you!
Your mental model sounds decent. I think there’s a few ways to describe things. I like to think of changes as a stable ID for something I want to accomplish, and a commit as the intermediate steps that make up a change. You can kind of think of a change as a branch… but I think that’s stretching it.
After your comments, the entire tutorial is more solid, but still I feel like I have gaps. My feedback would be to really focus on commits vs changes and define their relationships, what affects them, etc before you go into anything else.
Clarifying early on what exactly a change ID is, when it changes, and what the relationship between changes and commits is would really help, I think.
> The command-line tool is called jj for now because it's easy to type and easy to replace (rare in English). The project is called "Jujutsu" because it matches "jj".
What caught my interest:
* Separate operations and data
* Partial repos = no big repo issues, no need for shallow clones and such
* Proper and easy merging with no shuffled lines
* Patch-based model is much more intuitive (e.g. rebase and merge are the same operation)
* Conflict resolutions are stored and can be reapplied!
Just want to point out that this hasn’t been updated in a minute, and in particular, you’ll get some messages about branches being bookmarks now: https://github.com/steveklabnik/jujutsu-tutorial/pull/34
I have started on a second iteration of the tutorial in private, and am gonna see if I can get it in shape this weekend.
Happy to answer questions about jj!
English is so great and so confusing!
I swear the modern programmer doesn’t realize how extremely bad Git is. It does do a lot of things better than SVN. But it’s a long, long ways from “good” imho.
I blame GitHub. Git didn’t win because it’s good. Git won because GitHub won. If only HgHub had won instead, alas.
My dream VCS system would have a virtual file system, copy-on-write storage, and a system wide blob cache. The goal being to allow open source repos to commit *ALL* their dependencies, up to and including toolchains in many cases.
If you are already using Sapling then at least trying it should be fairly easy and familiar. You could also write a JJ backend for Mononoke and EdenFS if you wanted and then use it at work ;) You wouldn't be the first JJ user from Meta, actually...
We do have plans to explore server-side designs with virtual filesystems, chunked storage, etc. There's nothing concrete yet.
(Another benefit is that JJ is much easier to write patches and contribute to due to being a relatively new, small Rust project, whereas Sapling is much more developed but much bigger and harder to get into, I think.)
I'm not sure how I feel about JJ's "working copy commit". One of the great things about Meta VCS is that all commits are automatically backed up into the cloud. Which seems incompatible with the JJ model? Not sure. I think the D in DVCS is *wildly* overrated. 99.999% of projects are defacto centralized.
I'm #TeamMonoRepo 100% of the way. My background is gamedev and perforce. An industry which still uses Perforce because Git is poopy poop poop. The Git integration I want to see is the ability to easily sync a monorepo subfolder with an external GitHub repo. Syncing commits for internal projects that are open sourced requires a big ugly custom set of tooling. And I'd kind of like a way to do an "inner fork" within a monorepo if that makes sense.
If you're interested here's a pair of blog posts I wrote that have at least some of my thoughts on source control.
https://www.forrestthewoods.com/blog/dependencies-belong-in-... https://www.forrestthewoods.com/blog/using-zig-to-commit-too...
I don't particularly like git and for personal projects use fossil instead.
Without going through the whole tutorial, and doing a lot more reading, why should I consider using this over fossil?
What I care about is the tooling around it: GitHub and its ecosystem mainly. I also want my open source projects to be on GitHub specifically, and I don’t want to ask contributors to use something other than Git.
I've never really messed around with VCSes other than git and Subversion, there's people who really like Mercurial though, so I wonder how jj compares to that.
I thought about it and I don't know what a better name would be. Off the top of my Head, I know Perforce, BitWarden, Subversion, fossil and git. And then the abbreviations CVS, RCS and SVN.
Do any of these qualify as a descriptive name?
I recommend looking up Bartitsu (that Conan Doyle spelled Baritsu), a short-lived but very interesting martial art.
What you do is, you treat @ like the index, and you work on @-. This is the "squash workflow" https://steveklabnik.github.io/jujutsu-tutorial/real-world-w...