I just want to say that we all finally are using mostly the same VCS and that is actually an undervalued, beautiful thing. An actual “standard” that is almost universal.
It used to be such a mess with all the VCS systems and having to know all of them to commit on various dependencies from different projects.
I know that jj can be backed by git. But already it doesn’t need to be. Between this and other projects, I don’t have to squint too hard to see a future that looks like the past. I hope I’m wrong.
> I just want to say that we all finally are using mostly the same VCS and that is actually an undervalued, beautiful thing. An actual “standard” that is almost universal.
This bears repeating.
To further frame the importance of this, we've started seeing git being used as the deployment tool of some notable mainstream software projects such as nvm. This is only possible if a VCS becomes ubiquitous and a de-facto standard.
I think that's actually one of the nice things about JJ in comparison to many others (such as hg or Pijul): it uses Git essentially like a protocol or standard by which it communicates with other systems (and as a file-system standard, like using SQLite or something similar).
Essentially, it agrees that Git has become a de-facto standard as a file format and as a protocol, but that doesn't mean it can't have a very different approach to that file format and protocol.
It's similar to how HTTP can support a RESTful approach, or GRPC, or GraphQL or whatever else, and all these different systems can build on the same underlying technology.
To generalise a bit, this is really an example of the power of having a common language. I find this is generally undervalued. Having a common language at all is more important than having a "perfect" language. People are too eager to disrupt the language. We instead need to embrace it for what it is, learn to work with it, and only change it in small ways.
If you're learning French you don't argue with the language and try to get French people to talk how you want them to talk, you suck it up and do what they do. As with all things it's a trade off: you get to converse with everyone in France, but, yeah, you will have to deal with saying "le parking" etc.
For so many reasons, SVN to Git was a no-brainer but still constituted significant migration costs for existing teams and codebases: training, retooling, high-fidelity data transfer (you retained the commit history, right?).
For a tool with such wide adoption, motivating an ecosystem to move where there are many actors with different incentive structures, some of them will look and say ‘30% better isn’t even close to sufficient to spend time and $$$ on this. I would need ~10x better and/or a gain of altogether new capabilities impossible in previous tool to motivate that.’
It’s great that jj can be used independently without needing the whole ecosystem to move today, but once/if that part changes I’d expect it to be a long slog towards re-standardization if ever.
But jj likely already fully anticipated this given its compatibility with the Git wire protocol in the first place and I doubt it would ever give that up given the current landscape.
Primarily jj is different. And a lot of the "problems" it solves barely ever come up in git. And when they come up, its usually as "difficult" as "google the solution and enter the commands". And worst case scenario, someone has to manually copy paste some files around.
If this happened every day, I'd agree that we need a different system. But it doesn't.
In short, the situations where jjs advantages can really shine, and the advantages in these situations are simply not common enough / important enough to justify the headache of switching the world over to another VCS.
In an ideal world, "the better" solution wins.
In a pragmatic world of limited resources, "better" on its own is not enough. The differential between the new and the old solution has to be large enough to offset the cost of switching, and the more entrenched the existing solution is, the higher that cost will be.
Mostly everyone using the same standard is amazing. Power tools batteries are the glaring failure. Kubernetes gets a lot of shit for being complicated, which it should, because it is, but I'm glad that enough people use it to manage their fleet of computers that I don't have to learn too many special cases for managing fleets of computers.
git is good (good enough even) but not perfect. I’d love to see pijul receive funding for a small team for a couple years but we’ve got what we’ve got.
jj’s killer feature is git compatibility, obviously. For now it’s table stakes so we can pretend only git exists.
This got spammed a lot but does anyone actually use it in the wild?
We have This and Sapling (mercurial) for alternative git.
Back in 2014 up til 2018 we used mercurial , development workflow is a lot smoother and better in DX wise vs git but soon after bitbucket decided to cut mercurial we have no choice but to use Git since there is literally no opensource or cloud service mercurial `hub` in existence.
What you need for your CVS to be popular is not having a new CVS that do a thing a little bit different and better vs Git but to have a good GitHub alternative. In Git world there we have Gitea - which is very easy to setup and experience is much better than github , and gitlab for bigger orgs. Plus a good IDE support.
Sapling and JJ need something like that - built in or selfhostable.
JJ doesn't currently have a "native" repository format (or rather, it's in development and not ready for general usage), so right now a JJ forge wouldn't look too different from your usual Git forges.
Everybody who's using it right now uses it on Git repos on Git forges. I've been using it for months on my own and at work and I didn't make any changes to the infrastructure outside of my own command line usage.
It would be interesting to see what a JJ-native forge would even look like in the future, but I don't think anybody knows exactly what that would be right now! JJ is in development (but stable enough to work with) and people have only just started using it, so it's still in the phase of discovering what workflows are possible.
> Plus a good IDE support.
Now that's something I would love to see. Git tooling works mostly fine but due to how JJ's git backend works, it always thinks it's in a "detached HEAD" state.
Given than jj is compatible with git servers, does it matter? If you prefer jj, you can just use it on your laptop to just get shit done, meanwhile using whatever git server you're given.
I'm using it for everything now. The beauty of JJ is that everyone else on my team can keep on using git if they want, even if I'm using JJ on the same repo.
JJ should be compatible with any existing Git server. The project is currently maintained on Github, and I believe all the maintainers use JJ to work on the project itself. At work, I use JJ a lot with repositories hosted on Azure Devops, and that also works well (in some ways, better than Github).
This is using JJ's "Git" backend, which internally stores data as Git refs, and communicates with other servers the same way that Git does. There is a work-in-progress native backend, but this is still being developed and you need to explicitly opt into it if you want to try it out.
I'm using it day to day for my personal projects and at work. The thing that always annoyed me about ... work ... is that I'll be working on like 5 things, with 4 of them being code reviewed at my code reviewer's leisure. So I always end up with a crazy stack of branches, and as "main" changes, the burden of keeping everything up to date becomes painful. jj makes this all very easy! "jj rebase -d main" to clean up one of my topic branches. No interrupt to whatever I'm working on (as git checks out the files to your working copy and you resolve conflicts for each step in "git rebase main"). Conflicts can be removed at your leisure.
Something I always regretted doing with my many-topic-branches-out-for-review approach was making changes that depend on two topic branches. With jj, it's easy, you just "jj new qrs xyz" and now you have a new change on top of those two topic branches. If you add something in this commit that you want in one of your topic branches, "jj squash --onto qrs some/change/to/qrs.go" and now that change is in there.
It works well with Github and a PR per change. You create a PR with "jj bookmark create whatever" and then "jj git push --allow-new" to make "whatever" a remote branch. As you update that commit, "jj git push" adjusts the remote state as necessary. "jj git fetch" automatically adds bookmarks for upstream branches (so you can "jj new coworker/their-change" to test and modify their thing locally).
Finally, it works well when you have persistent changes that you don't want to commit but you do want to keep around. For some reason, we check in dev configs, and each engineer needs to modify them to run stuff locally. I have a commit called 'private: local setup' and that forms the base for each new (local) commit I work on. To do a PR, I squash my changes into a commit based on main instead of that commit. jj will avoid pushing anything with the prefix 'private: ' so I don't have to worry about leaking my keys, even though they are checked in locally. I wouldn't recommend managing secrets like this, but ... I didn't make this decision and jj handles it fine.
Overall, a huge improvement to my workflow. There have been times when I have so much stuff in flight that I just give up for the day until a few PRs get resolved. That never happens anymore. I can kind of work on whatever I want and let the world move at its own speed. Updating my work to account for PR comments or PRs merged before mine now takes seconds and never goes wrong. Truly an amazing tool and I wish I discovered this years 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?
As 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.
> 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).
For example? Or should I create my own in C using inotify/kqueue? Is there a library for jj?
The 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.
> 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.
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.
If 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)
jj 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#...
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/ (That being said, there may be bugs in jj itself.)
“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)
As 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).
Er, 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.
I 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.
I have colleagues who are big fans of it.
I gave it a try, but I really don't get what is the problem it is trying to solve. Like, what is it that I will be able to do that I couldn't do with git, and why bother learning it at all
I find JJ to be what you get when you take a step back, evaluate everything that works in Git and try to find a design that accomplishes all those things with the fewest amount of concepts possible. Like a Git 2.0, if you will.
You can do most of the same things, but it's easier to understand it intuitively so you don't need to google or give up on the more advanced usages. And the things you do everyday you can do with fewer steps.
Couple that with colocated repos, meaning I can use JJ while everyone keeps on using Git, there wasn't really anything holding me back.
> You can do most of the same things, but it's easier to understand it intuitively so you don't need to google or give up on the more advanced usages. And the things you do everyday you can do with fewer steps.
Rebase is not harmful, but thanks for your link. There are quite some people that do not understand rebase, and this link helps to get a grasp of how people can be confused.
- in section 2.2, they think that in a feature branch only the latest commit counts. You should not just be interested in how the tip of your feature branch compares to the latest main, but also into the logical sequence of steps your feat branch builds up a feature. In a rebase model, every step of your feature can be compared to main.
- in section 2.2, they conveniently omit what happens if you keep merging main into your feat branch. Your feat branch will show all useless commits telling you that "at this time, my feature diffed such and such from how main looked at at that time". "Oh, and here again a useless diff" "Oh and here again." "By the way, have a nice ball of diffs again". I don't fucking care. Why don't you just commit some info about the local weather at that time too or that your back was hurting on Wednesday 23th?
- "Rebase encourages siloed development". That claim is just ridiculous. If you don't want people to take ownership of a feature, by all means, forego branches. If someone wants to work on my feature, then we just agree that the public feat branch is to be considered public history. When the work finishes, someone can take ownership, (possibly clean up the mess with rebasing) and get it into mainline by rebasing on top of main.
> The problem is that that workflow is still ultimately harmful nonsense[0] that is based on a misunderstanding of version control.
The problem with that article is that it's utter nonsense and completely misses the whole point of rebase.
No one cares if under the hood a rebase is technically a merge that forgets where it came from. I mean, isn't that the whole point of a rebase?
The whole point of a rebase is to move your local branch onto the tip of another branch while preserving the local history. The goal is to simplify the repository history by eliminating irrelevant noise. That's not a problem, it's a solution. Is this too hard to understand? How can they possibly miss the extra forks and joins in their commit graph? Do they not see that? Do they spend any time looking at commit graphs?
It's ok if Fossil's devs want to force their opinionated take on VCS onto Fossil's users, but this does not mean they are right or have a point. In this case they are not only missing the whole point but also taking a completely wrong approach to mitigate it. The fact that they felt compelled to put up a page trying to present their case (and failing) is already telling.
If there is criticism to throw at Git, rebases clearly ain't it.
The author of that article clearly doesn't understand rebasing. They state that "the golden rule of rebasing" in the "Git rebase documentation" (actually just an Atlassian git tutorial) says that you should "never rebase on a public branch", when the tutorial they reference unambiguously states you shouldn't rebase a public branch onto your own local changes. Rebasing on public branches is the raison d'être of rebasing. The entire article seems like cope, the author deciding to bash rebase because they don't understand it.
> Have you ever wanted to store your version controlled repositories inside a Dropbox folder? Or continuously backup repositories to S3? No? Well, now you can!
This made me chuckle. In all seriousness, does jj afford anything new by connecting to filesystems more directly?
The main issue with git I've heard of is for projects, like video games for instance, that bundle text based code with a huge amount of non-text assets (audio, images etc).
I don't understand what causes gitissues here, is it storage? Or is it more attempting to map differences between non-text assets. Curious about whether jj's filesystem usage help here.
There's an anti-footgun heuristic that asks "are you sure", basically, if the file about to be tracked is >=1mb, saved a lot of asses a lot of times.
But also, if it is such a showstopper, you can disable auto-amend of _new_ files with snapshot.auto-track=none() config (or even something funky like src/*) - and recently jj status finally started showing untracked files too, it's very usable
Jujutsu (jj), a Git compatible VCS (89 points, 112 comments) https://news.ycombinator.com/item?id=41895056
Steve's Jujutsu Tutorial (158 points, 117 comments) https://news.ycombinator.com/item?id=41881204
Jujutsu: A Next Generation Replacement for Git (94 points, 80 comments) https://news.ycombinator.com/item?id=40908985
A better merge workflow with Jujutsu (135 points, 90 comments) https://news.ycombinator.com/item?id=40842762
Jujutsu: A Git-compatible DVCS that is both simple and powerful (673 points, 262 comments) https://news.ycombinator.com/item?id=36952796
2025-02-04 https://news.ycombinator.com/item?id=42934427 (234 points, 122 comments) Jujutsu VCS: Introduction and patterns
I assume that’s the inspiration for this link.
It used to be such a mess with all the VCS systems and having to know all of them to commit on various dependencies from different projects.
I know that jj can be backed by git. But already it doesn’t need to be. Between this and other projects, I don’t have to squint too hard to see a future that looks like the past. I hope I’m wrong.
This bears repeating.
To further frame the importance of this, we've started seeing git being used as the deployment tool of some notable mainstream software projects such as nvm. This is only possible if a VCS becomes ubiquitous and a de-facto standard.
Essentially, it agrees that Git has become a de-facto standard as a file format and as a protocol, but that doesn't mean it can't have a very different approach to that file format and protocol.
It's similar to how HTTP can support a RESTful approach, or GRPC, or GraphQL or whatever else, and all these different systems can build on the same underlying technology.
If you're learning French you don't argue with the language and try to get French people to talk how you want them to talk, you suck it up and do what they do. As with all things it's a trade off: you get to converse with everyone in France, but, yeah, you will have to deal with saying "le parking" etc.
jj is better.
If it's backed by git and doesn't break anyone else working on the repo, what's the problem?
For so many reasons, SVN to Git was a no-brainer but still constituted significant migration costs for existing teams and codebases: training, retooling, high-fidelity data transfer (you retained the commit history, right?).
For a tool with such wide adoption, motivating an ecosystem to move where there are many actors with different incentive structures, some of them will look and say ‘30% better isn’t even close to sufficient to spend time and $$$ on this. I would need ~10x better and/or a gain of altogether new capabilities impossible in previous tool to motivate that.’
It’s great that jj can be used independently without needing the whole ecosystem to move today, but once/if that part changes I’d expect it to be a long slog towards re-standardization if ever.
But jj likely already fully anticipated this given its compatibility with the Git wire protocol in the first place and I doubt it would ever give that up given the current landscape.
Care to point one concrete example?
Primarily jj is different. And a lot of the "problems" it solves barely ever come up in git. And when they come up, its usually as "difficult" as "google the solution and enter the commands". And worst case scenario, someone has to manually copy paste some files around.
If this happened every day, I'd agree that we need a different system. But it doesn't.
In short, the situations where jjs advantages can really shine, and the advantages in these situations are simply not common enough / important enough to justify the headache of switching the world over to another VCS.
In an ideal world, "the better" solution wins.
In a pragmatic world of limited resources, "better" on its own is not enough. The differential between the new and the old solution has to be large enough to offset the cost of switching, and the more entrenched the existing solution is, the higher that cost will be.
XKCD 927.
jj’s killer feature is git compatibility, obviously. For now it’s table stakes so we can pretend only git exists.
What you need for your CVS to be popular is not having a new CVS that do a thing a little bit different and better vs Git but to have a good GitHub alternative. In Git world there we have Gitea - which is very easy to setup and experience is much better than github , and gitlab for bigger orgs. Plus a good IDE support.
Sapling and JJ need something like that - built in or selfhostable.
JJ doesn't currently have a "native" repository format (or rather, it's in development and not ready for general usage), so right now a JJ forge wouldn't look too different from your usual Git forges.
Everybody who's using it right now uses it on Git repos on Git forges. I've been using it for months on my own and at work and I didn't make any changes to the infrastructure outside of my own command line usage.
It would be interesting to see what a JJ-native forge would even look like in the future, but I don't think anybody knows exactly what that would be right now! JJ is in development (but stable enough to work with) and people have only just started using it, so it's still in the phase of discovering what workflows are possible.
> Plus a good IDE support.
Now that's something I would love to see. Git tooling works mostly fine but due to how JJ's git backend works, it always thinks it's in a "detached HEAD" state.
As I understand it there's also a group of Googlers using it internally at Google with an internal to Google non git backend.
I only use git directly when I have to now.
(As others have pointed out, jj uses git as a storage/network layer, so you don't need a new forge to start using it.)
https://x.com/mitchellh/status/1845869748841832667
This is using JJ's "Git" backend, which internally stores data as Git refs, and communicates with other servers the same way that Git does. There is a work-in-progress native backend, but this is still being developed and you need to explicitly opt into it if you want to try it out.
Something I always regretted doing with my many-topic-branches-out-for-review approach was making changes that depend on two topic branches. With jj, it's easy, you just "jj new qrs xyz" and now you have a new change on top of those two topic branches. If you add something in this commit that you want in one of your topic branches, "jj squash --onto qrs some/change/to/qrs.go" and now that change is in there.
It works well with Github and a PR per change. You create a PR with "jj bookmark create whatever" and then "jj git push --allow-new" to make "whatever" a remote branch. As you update that commit, "jj git push" adjusts the remote state as necessary. "jj git fetch" automatically adds bookmarks for upstream branches (so you can "jj new coworker/their-change" to test and modify their thing locally).
Finally, it works well when you have persistent changes that you don't want to commit but you do want to keep around. For some reason, we check in dev configs, and each engineer needs to modify them to run stuff locally. I have a commit called 'private: local setup' and that forms the base for each new (local) commit I work on. To do a PR, I squash my changes into a commit based on main instead of that commit. jj will avoid pushing anything with the prefix 'private: ' so I don't have to worry about leaking my keys, even though they are checked in locally. I wouldn't recommend managing secrets like this, but ... I didn't make this decision and jj handles it fine.
Overall, a huge improvement to my workflow. There have been times when I have so much stuff in flight that I just give up for the day until a few PRs get resolved. That never happens anymore. I can kind of work on whatever I want and let the world move at its own speed. Updating my work to account for PR comments or PRs merged before mine now takes seconds and never goes wrong. Truly an amazing tool and I wish I discovered this years ago.
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?
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.
For example? Or should I create my own in C using inotify/kqueue? Is there a library for jj?
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.
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.
- 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)
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#...
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/ (That being said, there may be bugs in jj itself.)
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.
I'd like to introduce you to a couple of my former colleagues...
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.
And now people are saying it for jj.
Endless cycle it seems, with every new tool.
You can do most of the same things, but it's easier to understand it intuitively so you don't need to google or give up on the more advanced usages. And the things you do everyday you can do with fewer steps.
Couple that with colocated repos, meaning I can use JJ while everyone keeps on using Git, there wasn't really anything holding me back.
Care to point out any concrete example?
The problem is that that workflow is still ultimately harmful nonsense[0] that is based on a misunderstanding of version control.
[0]: https://fossil-scm.org/home/doc/trunk/www/rebaseharm.md
- in section 2.2, they think that in a feature branch only the latest commit counts. You should not just be interested in how the tip of your feature branch compares to the latest main, but also into the logical sequence of steps your feat branch builds up a feature. In a rebase model, every step of your feature can be compared to main.
- in section 2.2, they conveniently omit what happens if you keep merging main into your feat branch. Your feat branch will show all useless commits telling you that "at this time, my feature diffed such and such from how main looked at at that time". "Oh, and here again a useless diff" "Oh and here again." "By the way, have a nice ball of diffs again". I don't fucking care. Why don't you just commit some info about the local weather at that time too or that your back was hurting on Wednesday 23th?
- "Rebase encourages siloed development". That claim is just ridiculous. If you don't want people to take ownership of a feature, by all means, forego branches. If someone wants to work on my feature, then we just agree that the public feat branch is to be considered public history. When the work finishes, someone can take ownership, (possibly clean up the mess with rebasing) and get it into mainline by rebasing on top of main.
The problem with that article is that it's utter nonsense and completely misses the whole point of rebase.
No one cares if under the hood a rebase is technically a merge that forgets where it came from. I mean, isn't that the whole point of a rebase?
The whole point of a rebase is to move your local branch onto the tip of another branch while preserving the local history. The goal is to simplify the repository history by eliminating irrelevant noise. That's not a problem, it's a solution. Is this too hard to understand? How can they possibly miss the extra forks and joins in their commit graph? Do they not see that? Do they spend any time looking at commit graphs?
It's ok if Fossil's devs want to force their opinionated take on VCS onto Fossil's users, but this does not mean they are right or have a point. In this case they are not only missing the whole point but also taking a completely wrong approach to mitigate it. The fact that they felt compelled to put up a page trying to present their case (and failing) is already telling.
If there is criticism to throw at Git, rebases clearly ain't it.
Otherwise I also find it not really an improvement and a downgrade in terms of other tooling (editor etc.)
I.e. the typical Gerrit workflow
This made me chuckle. In all seriousness, does jj afford anything new by connecting to filesystems more directly?
The main issue with git I've heard of is for projects, like video games for instance, that bundle text based code with a huge amount of non-text assets (audio, images etc).
I don't understand what causes gitissues here, is it storage? Or is it more attempting to map differences between non-text assets. Curious about whether jj's filesystem usage help here.
Jj interacts with files in a way that ensures this can’t happen.
Jj is the same as git with regards to large non-text assets. But that’s just because it’s still young, it will gain good support eventually.
(And yeah it’s about storage and also about diffs. How would you fix a merge conflict in a PNG?)
Large file handling needs to be sane in any new VCS, IMHO, as this is a main failing of git (..without the extra legwork of git-lfs).
Edit: https://github.com/jj-vcs/jj/issues/80 Could maybe bring jj up to parity with git here
But also, if it is such a showstopper, you can disable auto-amend of _new_ files with snapshot.auto-track=none() config (or even something funky like src/*) - and recently jj status finally started showing untracked files too, it's very usable