For me, that's probably jj undo, just because it makes everything else so nice to just give a try. I really don't worry about making mistakes.
But for me, it's not so much features that git doesn't have, it's that the core is factored in a way that's more focused and orthogonal. The stuff that I used to like to do with git is even easier and more straightforward with jj. This is more of the result of a bunch of different design decisions and how they fit together rather than just some specific feature that's great.
Sounds like jj just simplifies the interface of some git commands, mainly. After talking to some jj enthusiasts here, I think we just have a different perspective about what needs to be simple and even what constitutes simple. There is probably some lingering unfamiliarity with git among jj enthusiasts as well. I don't want to teach git to people who are not programmers, but I wouldn't want to teach any programmer's VCS to them honestly. If you are a programmer, I think git is the best.
> There is probably some lingering unfamiliarity with git among jj enthusiasts as well.
I've heard this a few times. But from what I've seen, it seems like often it's the Git enthusiasts who seem to be unfamiliar with jj. I haven't heard from anyone who used jj for a few months and knew it well and then switched to Git.
I have never used jj, nor met anyone who used it in person. Given how new it is, you just won't find enough people who used it at all. I think git is like the vim of VCS systems and like vim there are some people who just don't think that way. I think jj might be more like emacs in that it has the initial appearance of being simple, but when you get into it more deeply you realize that it is not so simple after all.
I have used other VCS systems that made similar claims about being simpler, such as Mercurial. I think I got to be fairly expert at Mercurial before becoming expert at git, and even used it to interact with SVN repositories. (I've also used git for SVN. This is another thing git does better.) After actually learning git past the first few commands, I would never go back to Mercurial. I don't want to mix and match systems either. There are things I want git to do better, but I would not call these simple feature requests... They are more along the lines of advanced features that need to be extended or polished.
I can pick only one? Perhaps automatic rebasing then, i.e. that all descendant commits and bookmarks (branches) are automatically updated when you rewrite a commit, e.g. by amending into it.
I don't think I would want to rewrite all branches based on rewriting one of the ancestors of those branches. This only makes sense for local branches, and I just never have such a set of branches. Most rebases are to get ahead of upstream work, and I can't rewrite that. The rest are to rewrite commits that I made, and I collapse all those commits down periodically anyway. In the rare case I might be able to use this feature, rebasing all the other branches (realistically, probably like 1 or 2) would be easy enough to do manually with the feature described in this post. Rebasing and touching up commits is very easy with git interactive rebase. There are also features to automatically reorder commits with, e. g., `git commit --fixup` and `git rebase --autosquash`.
If you have others in mind then go ahead lol. I was just trying to make it easy.
> I don't think I would want to rewrite all branches based on rewriting one of the ancestors of those branches. This only makes sense for local branches, and I just never have such a set of branches.
Yes, it's only meant for local branches. When I used Git, I had a script for rebasing dependent branches. I remember that a coworker had written a similar script.
I think jj is generally more useful for people like me who often have lots of independent and dependent work in progress. If you mostly just have a one review at a time, there's much less benefit. Perhaps I would say that `jj undo` might be the most useful feature for users with simpler development (yes, I know about the reflog, but see the video I linked to in the other message).
I think this is generally only useful, if these branches don't need any other change for updating the ancestor. When they need than you need to work on the branch anyway and rebase other commits or add new ones on top, so you gain nothing compared to "rebase --onto" for each branch separately.
If you don't have anything to update then that would be somewhat pointless to me. You can also just rebase them, when you start working on the branch again or want to merge them.
--
For me branches also represent features, that should have clear boundaries, so when I work on one feature and that means, I need to rebase another one on top instead of being able to just merge them later, this indicates a spaghetti codebase where the interfaces between features are not properly defined and things depend on internals of other things.
>For me branches also represent features, that should have clear boundaries
I try to do this too but I often end up in situations where I have multiple incomplete (in testing, not merged) features with outstanding patches. Instead of one branch per topic, I end up with one branch for a bunch of related stuff. I then rebase and pause at the feature boundaries to do more testing. Sometimes, if I find myself doing this a lot, I will use the `exec` feature of `git rebase` to automate my testing.
I think rewriting all related branches can cause problems. It would be really weird to do interactively for one thing. The other problem is that you may have unrelated topic branches broken by such a change. If you have a broken patch X that reveals problem Y on branch Z1, but you are working on fixing that on Z2, you may lose your ability to reproduce the Z1 issue if X is fixed on every branch. What if you get conflicts on all those branches? What does this do to the reflog? Yikes! It seems more dangerous than git itself.
These complaints are very niche of course, but the problem of rewriting many branches at once is also very niche. It can cause more problems than it solves.
(sorry about the formatting here. I guess you'll have to copy & paste it to read it)
What I'm saying is that if I want to fix something in D, I do `jj new D` to create a new commit on top of D. Then I make the fix, run tests, etc., and then I run `jj squash` to amend the changes into D. The descendant commits (E through J) then get automatically rebased and the feature bookmarks/branches get updated.
I didn't follow what you about it other changes needed for updating the ancestor. Can you explain in the context of this example?
So what I am saying is that after you created D', it is true, that you need to run `rebase --onto` in git, while it is automatic in jj. But I think updating feature2 and feature3 is only really necessary to do now, when you want to change something in G-J also. If you don't and it wouldn't cause merge conflicts at all (logical and physical) then you could also just do this when you work on top of H or J the next time, so it wouldn't actually cause any more work in git compared to JJ.
--
The other thing I am saying is that I don't really let features depend on each other, I let them specify the API between them first and then develop them independently. Otherwise it is easy to violate boundaries. So the ideal is that any of G,H and I,J works with D,E,F and vice versa. Of course that is tangential and it doesn't always work that way.
I think you're right about people having trouble with `git reset` but it's really not that hard. There is also the newer `git restore` command which is somewhat easier. There are many individual functions which have an inverse, so the word "undo" might not be a good choice for git. You could make a `git undo` that does the `jj undo` logic with the reflog very easily. I'm not sold on the simplifications yet but to be fair I'm not trying to learn it either lol.
But for me, it's not so much features that git doesn't have, it's that the core is factored in a way that's more focused and orthogonal. The stuff that I used to like to do with git is even easier and more straightforward with jj. This is more of the result of a bunch of different design decisions and how they fit together rather than just some specific feature that's great.