> And for a chain of commits that all have conflicts, chances are fixing the first conflict automatically resolves all other conflicts in the chain, thanks to the auto-rebasing feature.
What happens if one is unlucky and the conflicts are not automatically resolved from changes to the first commit? Does that potentially imply more work overall than if one was using a VCS that forced conflict resolution earlier, like git?
It’s fundamentally no different than doing the same resolution in git.
The main advantages are that you can do the changes piecemeal, in any order, at any time, and by jumping around in the commit history however you need or want to.
Sometimes the best way to solve a conflict is by changing something before the conflict, or by moving pieces from one commit to another. Git doesn’t allow this, you can only do: fully fix commit 1, fully fix commit 2, fully fix commit 3, and so on.
No worries, it's still just another commit w/ conflict. If you want, solve those conflicts later.
Why is git's "forced conflict resolution" better, assuming the same workflow (local change+sync upstream) would produce the same # of conflicted commits?
git doesn't force conflict resolution earlier. It forces conflict resolution the moment you pull changes from upstream. jj allows you to go back to the first conflicting commit and then fix things there. That first conflicting commit is most likely a lot more similar to the upstream code than your newest commit and therefore it is easier to fix.
Jujutsu is built on top of Git, so it can benefit tools in the same ecosystem (forges, CIs, code quality tools, IDEs, plugins, etc).
I have only played a little with jj and hg, but I felt that jj has a more modern UX, learning from years of Git existence (and even influencing Git, like the new `git history` command [1]). On the other hand, hg was created in the same month as Git, both trying to improve the experience of the VCSs available at the time (april 2005).
Git already won through Github, the Linux kernel, and other important projects. Even if you like Mercurial's syntax better (I do) and wish it won (I do), that battle was over many years ago.
jj's data store is git. You can use jj while other people on your project just use git. There's no migration of data or history. You can use Github and all of the various git tooling that exists today.
As such, the initial cost of switching to jj is zero for individuals, teams, or projects. That's huge.
jj's ergonomics are significantly nicer. Fewer ways to shoot yourself in the foot, much better merge resolution, etc.
It is possible to move one step further: use own store, speak git protocol. In the end, it is about the commit-tree-blob model. I think, the main headwind is the broad decay of interest in computer science topics.
Where can I read on jj merge resolution strategies? LLM links to Arch Linux man page and other random stuff.
You can speak the git protocol over the network only, but one advantage of using the same storage on disk as Git and exposing it in the same way (in a manner that keeps jj/git in sync) is that git-based tools still work. So, people still get diff markers in the gutter of their editor buffers, random scripts that do `git rev-parse` or whatnot still work out of the box, etc. This makes the experience more seamless and imposes less friction on non JJ users, eg you do not have to write a patch and add a special case for JJ because `git rev-parse` failed to run and then ask pretty please to merge it (and then keep doing that forever as you are the only user).
It doesn't sound like much, but before I started contributing to Jujutsu I was a user of https://sapling-scm.com/ -- Sapling is fantastic. It stores data on disk in git format, but back then it was not exposed to the user by default -- the .git directory is hidden away. It actually ended up causing a lot of friction that random `git` commands would not work, or tools had other various git-based behaviors. These days, sapling has a "dotgit" mode (partially inspired by jj I assume) that puts the .git directory in the root dir, so `git` commands still work.
Beyond that though, speaking Git over the network only has other complications on the client side. In particular Git clients and servers negotiate what objects each side has (given what the client requests), and from that negotiation derives a list of needed objects to give the client, and then sends a packfile for it. This is all relatively expensive to do on demand, actually, so it would make the interactivity for network operations much worse if you need to wholly translate your storage into packed objects, etc. And doing it efficiently would require you keeping a cache around that is basically a git database anyway, so you might as well just go ahead and use it. Not the end of the world in terms of downsides, but a trade-off that adds some baggage.
Using a different data store breaks compatibility and dramatically increases the friction to switching to it. jj's superpower is that my usage of it is invisible. Right now I'm working on Github projects in jj where none of the other contributors are. Nothing about my usage of jj requires them to change anything they do.
Mercurial is too slow. Even with chg common commands like `hg status` may take hundreds of milliseconds. JJ is fast. Internally `jj log` taking more than 500ms is tracked as bugs.
Well I did not answer your second part of the question, only the first part of comparing Mercurial vs Git.
Now to the second part: I think speed still plays a role back when Bitbucket and Google Code provides Mercurial hosting and people were comparing Mercurial with Git. Eventually GitHub won the competition, so then we kinda stuck with Git.
Several jj developers (especially Martin and Yuya) are former mercurial developers.
jj borrowed quite a few things from mercurial.
So, jj can be thought at least partially as a spiritual successor. Meta's Sapling is in a similar position. From this perspective, the key feature of both is transparent git repo and git remote support (hg can speak git as a foreign language, but it's limited)
Others have answered about traction. As a one-time Mercurial user, I think the single most significant addition is first-class conflicts, so that dealing with them doesn't stop the world but can be deferred until I'm working on a particular conflicted change. (That also eliminates the need to ‘evolve’.) Easy undo is also nice.
My relatively ignorant take is that it's pretty similar to Mercurial, except that it's compatible with git repos, which is also the answer to why it might get more traction. At least from my standpoint, it also doesn't need to get traction, because I freely use it with git repos without any of my coworkers needing to use it as well (although they might! I have no idea, just like they probably don't know I use it)
Technically, you can still tell actually - jj writes a "change-id xyz..." in the git commit object header, which remains there as it's pushed around. It's just typically not made visible by regular things. (I wonder what other random garbage has been hidden in git commit headers that noone has seen)
Huh, fortunate for it that GitHub (especially) preserves it then!
I wonder how guaranteed that is, can imagine GH deciding to 'clean' it (how much data can you put there theoretically? Or to close a range of potential security issues) and suddenly relatively niche but genuine uses like jj's change-id are unintentionally not preserved.
Cleaning it would change the commit ID, so a forge cannot clean it even if it wanted to (not without rewriting all descendant commits too and breaking signed commits, at least).
The change-id is exactly as much part of the commit object as the author/committer name/timestamp, description, parent commit ID, tree, and participates in the commit hashing as those do.
Will this have any chance if Jujutsu/jj doesn't get more traction? The effort to learn a new VCS is less than for a programming language, but many developers have not learned git in depth, and Mercurial and others have not gained a lot of traction.
I'd argue that the reason a lot of developers have not learned git in depth is because it's actually kind of terrible from a UX standpoint (lots of inconsistent naming of things and somewhat leaky abstractions), and that Mercurial faced an uphill battle in large part because it lacked compatibility with what people were already using. I haven't used Mercurial, but from what I've heard quite a lot of how jj does things is similar to Mercurial, just in a way that's compatible with git. I haven't used git directly for over a year in favor of using jj despite exclusively using git repositories, and no one I've worked with has even needed to be aware.
> I'd argue that the reason a lot of developers have not learned git in depth is because it's actually kind of terrible from a UX standpoint
Not really. I remember my early years with git and the favt was that I never needed more than clone, add, commit, pull and push. While I’ve done some mistakes that got ne to learn more, especially with creating branches and undoing. I’ve never needed a lot, even when I started using GUI which exposed more concepts.
Why? Because I have no understanding of version management and how it’s useful in a dev workflow/release process. I was just using it for checking in work.
Since then, I’ve read the “Pro Git” book, learned how devs and teams handle versioning and devel a good understanding of how git can help me in my coding process and general software development. And it’s very good at what it does.
Yes, really. You just proved the other poster’s point. He says “a lot of developers have not learned git IN DEPTH” and you respond by saying that’s not true because you’ve gotten away with just using a small subset.
Git is quite powerful, but the cli is a train wreck of complexity and inconsistency. Learning the options to one git command means you’ve learned the options to exactly one git command. No other git command is required to use the same terminology. Personally, I was stuck in “git basics land” (all the basic commands you list) until I adopted Magit in Emacs. IMO, the Magit team deserves a medal for making git usable at an advanced level.
I don’t have an opinion about jj yet, but no one can hold up git as a pinnacle of great source control. Yes, it’s powerful, but it’s a UI train wreck.
> He says “a lot of developers have not learned git IN DEPTH” and you respond by saying that’s not true because you’ve gotten away with just using a small subset
You forgot the “because it's actually kind of terrible from a UX standpoint”. My stance is against that. I haven’t learned git in depth because I never knew any other workflow than code and check in the changes. There’s not a lot of guides on how version control can help in the software development process.
It wasn’t until I got involved into OSS that I learned more which in turns give me the motivation to use and learn about git in depth. I’m also using magit (after a tour in various GUI) but for me it is to git what vi is to ex. Direct interaction instead of a command prompt.
> I’m also using magit (after a tour in various GUI) but for me it is to git what vi is to ex. Direct interaction instead of a command prompt.
I'm not sure I understand how "I use a specific text editor with a specialized interface into git that's superior" is a counterargument to the first-party tool having horrible UX. That seems basically the exact same as what I was saying about jj, except via emacs instead of a CLI. Either way, we've opted out of the actual experience of the tool in favor of using an alternative tool that operates on the version control.
Magit doesn’t anything that is not readily available in git. Most of magit usefulness comes from “active objects” (meaning you can act directly on the report of some commands like git-log) and quick command construction due to transient and autocompletion.
Can you give me a a terse summary of what "checkout" means that doesn't involve needing to either list or ignore several very different types operations?
I would say “align the worktree (or part of it) to a specific state previously saved in the repository.”
The repository is a store, you check out the previously saved instance of a file, a group of files, or a subtree. In that regards, switching branches and restoring files is actually the same thing. A commit stores whole files and branches are pointers to commits (which update themeselves).
What is version control to you? For me it’s basically being able to store and retrieve snapshots of code at different instances of time, where each instance has its own significance. Checkout have a very precise meaning in that regards, just like add and commit.
Maybe you can explain how is it leaky based on your understanding of version control?
Not really. Learning the piano and learning music theory is two different things but tied together. One is skill and muscle memory, the other is theory and understanding. It’s the same with git and version control. One is a process and the other is a tool.
I don't think this framing makes much sense; playing piano isn't a "tool" that you use to achieve some other task, it's literally the goal itself. Using git is not the goal, it's the tool I use to do something else, and needing to learn the underlying theory of how a tool works that's only a small part of how I do my job is not a good user experience.
The goal is to produce music, and such music is generally constrained by music theory. Using git is to version control some software, and version control is dependent on the programmer/team workflow.
At the team level, it’s guided by the release process, configuration management, which version is canonical. At the programmer level, it’s usually guided by how to switch between task, how easy to explore an idea and save the resulting experiment, how to reset the code to a know state and how to replay a previous changes on top of new changes.
So you discern what you want to do (which is independent of the tool), the learn how to use git to do them. If you start from git, you’re going to be confused, just like someone opening autocad with no knowledge of engineering drawing.
"Properly" is doing a lot of work here (Claude would say it's load-bearing ;) If one's needs are modest, then no, the 4-5 basic operations don't need a 400-page book to understand, and are quite proper for version-controlling one's software.
As a Mercurial fanboy, git took off thanks to being from Linus, and a requirement to contribute to the Linux kernel, from there the adoption wind was in motion.
As someone who was a mercurial fanboy too, critical element was that Github happpened for git while mercurial had nothing comparable - and before anyone points at bitbucket, it fucking sucked in UX
It was huge problem for Git adoption, that's why I mentioned GitHub
EDIT: GitHub had probably the first UX where I actually liked what I got, compared to various earlier git based ones, or the horrible CVS and SVN ones where clicking on a file name definitely didn't do what you expected.
I barely remember Bitbucket from the mercurial era but I do recall that while it was better than some, it was still worse than GitHub, whose "here's default branch's HEAD, plus auto-opened and formatted README" was really a game changer
TBH learning git in depth was a hindrance for me learning jj - for my first few weeks I kept instinctively looking for complex solutions to simple problems and being confused, when the answer was always "use the tools you already know"
As a concrete example - git has one set of commands for managing commits, a different set of commands for managing the index, a third set of commands for managing stashes, a fourth set of commands for managing the working directory, and a fifth set of commands for managing conflicts -- in jj all of those things are a single concept with a single set of commands, equally (if not more) powerful, but also simpler
What happens if one is unlucky and the conflicts are not automatically resolved from changes to the first commit? Does that potentially imply more work overall than if one was using a VCS that forced conflict resolution earlier, like git?