4 ms·
I've read a few small overviews of jj. One thing that's off-putting as a git lover is that while git is truly append-only (except refs), jj seems quite "mutable
by lytigas 2y ago
I've read a few small overviews of jj. One thing that's off-putting as a git lover is that while git is truly append-only (except refs), jj seems quite "mutable" by comparison.
Say I'm messing around with the commit that introduced a bug, somewhere deep in the history. With git, it's basically impossible to mess up the repo state. Even if I commit, or commit --amend, my downstream refs still point to the old history. This kind of sucks for making stacked PRs (hello git rebase -i --autosquash --update-refs) but gives me a lot of confidence to mess around in a repo.
With jj, it seems like all I would have to do is forget to "jj new" before some mass find+replace, and now my repo is unfixable. How does jj deal with this scenario?
- phildenhoff 2y agoIf you want to “checkout” some previous commit, jj has your back in three ways - first, that commit that’s been merged to main is marked as immutable and, unless you add a flag to say “I know this is immutable and I want to mutate it anyway”, you can’t mutate it - second, as part of your regular workflow, you haven’t actually checked out that historical commit. You created a new, empty commit when you “checked it out” using “jj new old_commit” - third, you can use jj undo. Or, you can use “jj obs log” to see how a change has evolved over time (read: undo your mass find+replace by reverting to a previous state)
- ninjamuffin99 2y ago“jj op log” shows you the operation history, which you can then “jj op restore” and point to where you want to restore to :) (disclaimer: im still jj newbie, but this has gotten me out of the snafus ive put myself into while learning g)
- OccamsMirror 2y agoCan I ask what your motivation was for trying jj? I'm always keen to explore new things but I don't have many complaints about git. I'm wondering what this solves that made it attractive for you.
- ninjamuffin99 2y agoi’ve always been interested in improving the git workflow i have for my small team (usually 2-3 other programmers), i think particularly hopping branches/commits, merging changes, rebasing and reorganizing history, i think git does suffice for that stuff if you know the commands, but jj makes it feel so fluid and easy to do, and having enough depth to get as expressive as you need to be a lot of other tools ive found were lacking for one reason or another, and mightve not been git compatible. with jj you can hop between git and jj commands as you please, essentially full compatibility with git
- ssivark 2y agoI was always very frustrated with git workflow for working on multiple features/bugfixes simultaneously (multiple branches [1]). Changing between them, or combining them for testing is tedious -- constant stashing, switching, cherry-picking. Conflicts fit very poorly into git's version control model - you can't just tell git to ignore some conflict and continue for the moment so you can take care of it later. You have to stop the thing you wanted to focus on and instead babysit git because it found a conflict. Etc. These are less of an issue once you've molded yourself to fit into git's strange ways, but jj feels like a much nicer tool -- especially for beginners, but feels like it frees up cognitive space even for more experienced folks. You can focus less on the tool and focus more on what you actually want to do. [1]: I've tried using multiple working trees, but that workflow never really "stuck" with me.
- jrockway 2y agoI've done the multiple trees thing too, and agree it didn't work very well. jj solved the biggest problem for me, which is how much time you spend rebasing when you have 1 PR = 1 stack of commits on top of main. It's easy enough to work on multiple branches this way, but it's a lot of repeated pain when `main` diverges and your changes on top are still out for review. (I honestly just started squashing all of my commits before review, so I would only have to resolve conflicts once.) jj fixes all of this. I especially enjoy working on a 3rd pending change that refers to the previous 2 pending changes; `jj new june/feature-1 june/feature-2` and then you add feature 3 there. You can even `jj squash --into june/feature-1` if something makes more sense being in a prior commit. It's all very wonderful if you are working with other people and you can't immediately mutate `main` upon finishing some work.
- jjfanboy 2y agoEr, well, never type `jj edit` and this will never be an issue? I exclusively move in a jj repo with `jj new` and `jj squash` or `jj squash --to <rev>` as appropriate. I've been using it 8+ hours daily for months and have never, ever even thought of having this issue.
- porridgeraisin 2y agoI find it quite funny that this is exactly the kind of the thing "just don't use ... 8+hours daily ... Never had issues ..." that people who remain with git say. And now people are saying it for jj. Endless cycle it seems, with every new tool.
- jjfanboy 2y ago`jj edit` is specifically and exclusively for mutating existing commits. Thus, if you're worried about mutating existing commits, don't use it. What exactly is so hard to understand here? You're not making the gotcha point you seem to think you are - it's not like it's some common command that is hyper-overloaded and has to be used specially. Just another example of the usual HN skepticism that isn't even skepticism, it's just smug ignorance. It's so exhausting. But sure, the countless people that keep claiming its the single biggest tool improvement in some time are just idiots? suckers? hype-beasts? making it up? or what? Like, the irony of you assuming that it must be as convoluted and hard to use as git is just... awesome. I love the Git defenders that literally can't fathom that there is actually a better mental model or simpler tool, and can't even be arsed to try it and see.
- eproxus 2y agoWith JJ you can even override the ref spec of what should be considered a mutable commit. Feel free to set it to all commits and JJ will not allow you to mutate anything unless you pass the --ignore-mutable flag. For example, I've configured it for me to make any commit by anyone else mutable regardless of branch: [revset-aliases] # To always consider changes by others immutable: "immutable_heads()" = "builtin_immutable_heads() | (trunk().. & ~mine())"
- cornstalks 2y ago> With git, it's basically impossible to mess up the repo state. I must be a wizard because I’ve lost count of the number of times I’ve messed up my repo’s state. I jest. Kinda. I know that git’s state might technically not be messed up and someone skilled in the ways of git could get me out of my predicament. But the fact that I’m able to easily dig myself into a hole that I don’t know how to get out of is one of git’s biggest issues, in my opinion.
- bboygravity 2y agoTotally. That hole is very easily dug with git: use ctrl x ctrl v to move files around commit boom, you've lost history for those files (file tracking only works in theory, not in real life), let's say you don't notice (very easy to not notice) commit some more, merge discover your mistake tons of commits back good luck fixing that, without digging a bigger hole. And that's one of 100's of examples in which git just is really really not fun or user friendly.
- Izkata 2y ago> use ctrl x ctrl v to move files around commit boom, you've lost history for those files (file tracking only works in theory, not in real life), let's say you don't notice (very easy to not notice) This is one of the things git excels at: You didn't lose your history because that's not how git handles it. Git might be the only version control that can actually handle your case (renaming files without using a special command) - it looks for file similarity between a deleted file and an added file in the same commit, with various flags to make this look in broader places. "git mv file1 file2" is almost identical to "mv file1 file2" + "git add file1 file2" (it also handles unstaged changes instead staging them)
- bboygravity 2y agoI keep reading explanation similar to yours, yet it obviously doesn't work in my case. I'm probably doing something dumb/wrong, some setting somewhere, wrong OS, whatever it is: it proves my point that git is harder than it should be.
- MrJohz 2y agoAs others have pointed out there's `jj undo` and other tools, but they all rely on the fact that JJ is less mutable than it seems. Internally, JJ is still backed by an append-only tree of commits. You don't normally get to see these commits directly, but they're there. A change (i.e. the thing you see in `jj log`) is always backed by one or more commits. You can see the latest commit in the log directly (the ID on the left is the change ID, the ID on the right is the commit ID), but you can also look back in history for a single change using `jj evolog`, and you can see all commits using `jj op log`. This ensures that even if you were to exclusively use `jj edit`, never made a new commit, and kept all your work and history in a single change, you could still track the history of your project (or the "evolution", hence the name evolog). It would be kind of impractical, but it would work. The only caveat here is that, by default, JJ only creates new snapshots/commits from the working directory whenever you run the CLI. So if you made a large change, didn't run any JJ command at all, then made a second large change, JJ would by default see that as a single change to the working directory. To catch these issues, you can use a file watcher to automatically run JJ whenever any file changes, which typically means that JJ makes much more frequent snapshots and therefore you're less likely to lose work (at the cost of having a file watcher running, and also potentially bloating your repository with lots of tiny snapshots). Note also that the above is all local. When using the git backend, Jujutsu will only sync one commit for each change when pushing to a remote repository, so the people you're collaborating with will not see all these minor edits and changes, they'll only see the finished, edited history that you've built. But locally, all of those intermediate snapshots exist, which is why Jujutsu should never lose your data.
- baq 2y agoThe first time I’ve tried to prepare a set of commits to push out I found out the hard way that merges cannot be undone - and I’m not sure which of the commands were doing a merge.
- arxanas 2y agoMerges can be undone. Either you can manually remediate by `jj abandon`ing the merge commit so that it's not visible anymore, or you can restore the entire repo state to a previous point in time with `jj undo` or `jj op restore`, or you can do some remediation in between those two extremes. Off of the top of my head, `jj new` and occasionally `jj rebase` can create merge commits; I don't recall any others.
- arxanas 2y agojj is pretty much just safer than Git in terms of the core architecture. There's several things Git can't undo, such as if you delete a ref (in particular, for commits not observed by `HEAD`), or if you want to determine a global ordering between events from different reflogs: https://github.com/arxanas/git-branchless/wiki/Architecture#comparison-with-the-reflog https://github.com/arxanas/git-branchless/wiki/Architecture#... In contrast, jj snapshots the entire repo after each operation (including the assignment of refs to commits), so the above issues are naturally handled as part of the design. You can check the historical repo states with the operation log: https://jj-vcs.github.io/jj/latest/operation-log/ https://jj-vcs.github.io/jj/latest/operation-log/ (That being said, there may be bugs in jj itself.)
- swiftcoder 2y ago> With git, it's basically impossible to mess up the repo state I'd like to introduce you to a couple of my former colleagues...
- cube2222 2y agoAs other commenters have mentioned, there's `jj undo`, but you can also configure a set of immutable commits (by default it's the main branch and heads of untracked branches) and jj will stop you from changing those unintentionally (there's a flag you have to explicitly set if you want to force it).