4 ms·
How does it compare against Facebook's Sapling? https://github.com/facebook/sapling https://github.com/facebook/sapling
by iFire 2y ago
How does it compare against Facebook's Sapling? https://github.com/facebook/sapling https://github.com/facebook/sapling
- rjzzleep 2y ago> Mercurial & Sapling: There are many Mercurial-inspired features, such as the revset language to select commits. There is no explicit index or staging area. Branches are "anonymous" like Mercurial, so you don't need to make up a name for each small change. Primitives for rewriting history are powerful and simple. Formatting output is done with a robust template language that can be configured by the user. Can anyone explain why people want something like JJ? Is it simplicity? I actually quite like the staging and index in git. Although it took me a while to grok. Looking at the other thread though I don't think it's more simple. It's just different. https://news.ycombinator.com/item?id=43020180 https://news.ycombinator.com/item?id=43020180
- MrJohz 2y agoI agree that you probably want to keep staging, but one of the advantages of JJ is that staging is just a change* like any other change in your history. There are a couple of different ways that people use JJ, but I normally use the "squash" approach. When I want to make a new branch/pr/etc, I run `jj new master` (to create a new change off the master bench), and then I run `jj new` again. This gives me two empty changes - the older change is where I'm going to store my work when I'm finished, and the newer change is where I'm going to actually be working. This functions like staging. As I edit files, the staging change fills up. When I think I'm finished, I can run `jj diff` to exactly what's in my staging change. If I want to keep all of it, I can run `jj squash` to squash the entire change into the parent change, or I can run `jj squash -i` to interactively squash the bits that I want to keep, and keep the rest in staging. You might argue that we've just reinvented the wheel - we used to have a pseudo-commit as our staging/index, and now we have a JJ change, but we're still doing the same thing with it. This is true, but the value of having our staging area be a change, i.e. a first class entity in our VCS, is that we don't need to special case it any more. Every command that works for our staging area works for any other change in our history. This is simpler because there's less stuff going on (fewer commands, fewer concepts), but we still have the same capabilities as before. On top of that, because our staging area is just another change, it is automatically stored in the local repository history. This means that if I've got stuff staged and I want to create a new branch somewhere else, I can do `jj new master`, and the stuff I've got staged will stay where it is. This also removes the need for an explicit stash: if all the work I'm doing is already part of a change, I don't need to create temporary "stash" commits to store them, they're already stored. Again, fewer commands, fewer concepts. Just by itself, I find this feature really helpful because it simplifies how I need to think about changes a lot. It's so much easier to navigate around a repository like this. But it's just one of the features that has been simplified from existing VCSs. For example, you've also got automatic rebases - you can make a change to an older change (either directly or using something like `jj squash`), and all the parent change will automatically get rebased. Sometimes this causes conflicts, but it never fails. Instead, conflict tracking is part of the history itself. This allows you to fix conflicts in your own time - you're not put into the "rebase world" like in Git, where Git needs to statefully remember that it's currently doing a rebase, and you need to use different commands to resolve a rebase conflict than you need to commit a merge conflict, say. No, conflicts are first-class, which again massively simplifies how you interact with the repository - fewer commands, fewer concepts. This is what I think people mean by simple - it's not simple in the sense of "make everything easy by wrapping it in an abstraction", instead it's simple in the sense of "find the ideal underlying model to expose to the user". Version control is always going to be fairly complex, but JJ feels like something that is very close to the minimum complexity required for a VCS: no simpler (because then it wouldn't work very well), but also but very much more complex. * "Change" in this context refers to JJ's equivalent of commits, i.e. the individual rows you see when your run `jj log`.
- kemayo 2y agoI'm sympathetic to the simplicity argument. I've recently had to help someone who's new to coding with some getting-started-with-git issues, and it's definitely reminding me of the appeal of a system that you can't screw up in various interesting manners and then need someone who understands its inner workings to fix.
- MForster 2y agoYou can still use a similar workflow as with the index. The difference is that the staging area is modeled as a commit, so it's not another concept that will take a while to grok. Same with the working copy.
- mpalmer 2y agojj is nicer to learn first, but also, knowing both git and jj I do pick jj. Significantly nicer UI, very simple but powerfully expressive DSLs for formatting logs and selecting revisions to log, respectively. For me it clicked when I really grasped how the latter DSL (called the revset language) wasn't just for selectively logging, it was for selecting commits/changes to act upon. The revset grammar is about specifying subgraphs of the graph of changes. Using it, and taking advantage of jj's by-design automatic rebasing of downstream commits, you'll eventually think nothing of rebasing N branches in a single command. Even conflicts are less trouble when they crop up during auto-rebasing. jj leaves conflicts on the change where they originated, and marks that commit (and all downstream ones) as conflicted. Fixing conflicts is no longer a "drop everything and fix" matter; you can decide when to fix them without delaying work on other parts of the tree. Haven't even gotten into the optional auto committing on every file change (it's better than it sounds). You might miss the staging area for a bit, and then you realize that there isn't really a difference between the staging area and a "current commit" that stays up to date on its own. I guess what I'm saying is I would recommend it.
- recursive 2y agoI've wished I could turn the staging area off in git since before jj was a thing. If you like how git works, then you probably prefer it to the alternatives. There are things I like about git, but some of its design choices are hard for me to understand.
- sunshowers 2y agoJujutsu has all of the power of the index without actually having the index as a separate construct -- index operations become commit operations. It is quite meaningfully simpler than Git as it can express the same degree of power (actually a lot more) through fewer concepts.
- arxanas 2y agoI don't think the cheat sheet in that thread demonstrates any of jj's improved expressive power, such as revsets or first-class conflicts. I gave an example of something difficult do in Git here: https://news.ycombinator.com/item?id=43022367 https://news.ycombinator.com/item?id=43022367
- rtpg 2y agojj makes it super easy to "fix up" your commit tree to what you want it to look like. "Oh I forgot to make a change in this commit and I'm 4 commits in..." -> "I can go change that commit and everything else magically rebases on it". It treats changes as this conceptual thing, and the whole immutable commit thing as a backing store but not how _you_ are looking at a problem. Or at least not how I look at it. I added a test, put in a new feature, updated the readme. Those changes are not about all the metadata around the change, they're the change. Of course you still have the immutable commit graph when you want to _really specifically_ talk about a certain commit, but for most intents and purposes it's the changes that matter. jj gives you similar workflows to git in the easy case. In the hard cases, jj makes it easier to do the work than git. So it's nicer!
- gpm 2y ago> jj makes it super easy to "fix up" your commit tree to what you want it to look like. I hit this today in a fun way. I was working along as one does, and needed to write a parser for a simple s-expression based language. So I did that fairly quickly, added a few tests which appeared to pass, and kept on working. A few commits later I reached a point where I needed to manually test my code. And promptly hit a stack overflow in the parser. A few minutes of debugging I understood the issue (I'd used the wrong function and failed to require brackets around a nested s-expression) - except I could have sworn my tests should catch it. So I ran my tests manually, and lo and behold they did catch it. Turns out that there was a bug in the tool I was using to run my tests [1] that was masking the test failure. I had completely broken my tests for the last few commits (all of them since I wrote the parser). Anyways, I went and fixed the tool, but by now on my main repo I had fixes for the last few commits all mixed together with a fairly large WIP commit. Thankfully instead of making this the frustrating game of rebasing with git, jj makes it just take a few jj split (select changes you want to split off, sort like git add -p); jj squash (merging changes into the existing commit) commands. Could I have fixed up the previous commits with git? Of course. But it would have made a frustrating hour even more frustrating. [1] https://github.com/Canop/bacon/issues/326 https://github.com/Canop/bacon/issues/326
- Izkata 2y ago
- MForster 2y agohttps://jj-vcs.github.io/jj/latest/sapling-comparison/ https://jj-vcs.github.io/jj/latest/sapling-comparison/
- Shish2k 2y ago> Sapling supports cloning, pushing, and pulling from a remote Git repo. jj also does, and it also supports sharing a working copy with a Git repo, so you can use jj and git interchangeably in the same repo As a minor update - sapling now also supports the .git on-disk formats so that you can use git and sl interchangeably in the same repo
- mmmulani 2y agoI tried out both for a week each and much prefer Sapling. jj always, automatically turns your current state (even if it's empty) into a "change" which is like a commit (it has a hash). in practice, this was actually incredibly annoying. when working in git, you often think about the current commit you're on, and amending/making a new commit. with jj, you're actually making "changes" (which are like commits) constantly. it's also so infuriating that there are two sets of hashes, jj changes and git commits, and they are not the same/interchangable. on the flip side, sapling has been a breeze. it does force you to one commit per PR (which might be annoying to some but if you're going to squash the commit into main when you commit, why not do it locally too). its inter-op with github is really nice, you can do `sl goto pr1234` and it will just bring you to the code for pr #1234 (and fetch it in the process if you don't have it locally).
- jjfanboy 2y ago> . when working in git, you often think about the current commit you're on, and amending/making a new commit. with jj, you're actually making "changes" (which are like commits) constantly I don't know what this means, and it seems like a fairly large misunderstanding.
- stouset 2y agoWhat did you find annoying or infuriating about this? It’s quite possibly jj’s most beloved feature. Since all of your changes are constantly being recorded, you're covered by your VCS even if you don’t commit. As a 1+ year jj user now, I can’t think of a single time I’ve needed to use a git hash. They’re there underlying things, but you’re always just using revision IDs.
- eitland 2y agoHaven't tried jj, but one thing that immediately strikes me is that for us who use IDEs, git hashes are all that we can see in that view. I've been considering trying out jj and thought it could work since it uses git as store, but if I need to keep track of different hashes based on if I access version control from my IDE (primarily IntelliJ for now) or from my command line, that seems like an actual problem to me. (I'm also used to work in the command line and I prefer it to point and click for many things, but version control is one of the things that I much prefer do approach from the same place I write my code.)
- sophiebits 2y agoThe first testimonial on this page is from Rain who has over 1,000 commits to the Sapling project and provides some context: https://jj-vcs.github.io/jj/latest/testimonials/#what-the-users-have-to-say https://jj-vcs.github.io/jj/latest/testimonials/#what-the-us...
- sunshowers 2y ago(Hi Sophie!) I still stand by my testimonial! My greatest achievement has been convincing Steve Klabnik to try out Jujutsu. I also saw a comment from JJ's lead author martinvonz, where he pointed out that adding new functionality is much simpler to jj than it is to older systems like Git and Sapling/Mercurial. Having each spent many years working on source control, both Martin and I came to a general belief that a lot of implementation complexity comes from the modal states created by merge conflicts. Because Jujutsu's core UX is more straightforward, this is less of an issue and Jujutsu's devs can prototype changes quicker.
- Timothee 2y ago> My greatest achievement has been convincing Steve Klabnik to try out Jujutsu I came across jj from a recent Bluesky post by Steve Klabnik who was talking about having to learn something with git. That seemed very odd to me. I then gathered that he (and many others in the comments) had been using jj exclusively for some time. I haven't had time to give it a try, but I definitely will. Your achievement has ripple effects.