zlacker

[parent] [thread] 22 comments
1. wakawa+(OP)[view] [source] 2025-12-05 23:50:49
This particular tip is basic. It just describes how to copy changes from one branch to another with one kind of rebase. But there's always someone who is learning git for the first time and may not even know how it's used.

Git is simple enough and has features and capabilities that jj does not have. Contrary to popular belief, git is not hard to use. I refuse to use any "simpler" system that is slower or less feature-rich than git. I don't even want to learn another commit graph model, because git's model is very good. About 95% of what people like yourself call "git nonsense" consists of useful features that many people would be annoyed to not have.

I believe that a large number of git or general VCS users have no idea about commit hygiene. They have not had to cherry-pick or edit commits, and have no idea what to do about conflicts. To people like that, git's features and methods will appear especially foreign.

I looked over jj specifically many moons ago and concluded it would annoy me and not function at my job. I forgot what the reasons were. One reason was most likely because I need submodules and worktrees to work. I just looked at its FAQ, and saw a bunch of nonsensical new terms as well. Nothing is more compatible with git than git itself, and I am very satisfied with how well git works for me.

replies(2): >>stevek+u2 >>martin+wz
2. stevek+u2[view] [source] 2025-12-06 00:12:11
>>wakawa+(OP)
submodules aren't native with jj, you use git commands to manage them, and it works fine. Eventually there'll be some sort of native support.

worktrees are called "workspaces" in jj, but are the same.

A lot of people find jj easier to have good commit hygiene with, and find it simpler and more powerful, not less. But that said, if you're happy with git, you should continue to use it.

replies(1): >>wakawa+gi
◧◩
3. wakawa+gi[view] [source] [discussion] 2025-12-06 02:42:54
>>stevek+u2
What is the most useful feature of jj that you think git doesn't have?
replies(2): >>martin+2v >>stevek+XN1
◧◩◪
4. martin+2v[view] [source] [discussion] 2025-12-06 05:06:22
>>wakawa+gi
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.
replies(1): >>wakawa+2C
5. martin+wz[view] [source] 2025-12-06 06:21:07
>>wakawa+(OP)
> I don't even want to learn another commit graph model, because git's model is very good.

I agree. That's why jj uses practically the same model. That's how Git can quite easily be used as a backend.

> I just looked at its FAQ, and saw a bunch of nonsensical new terms as well.

Like what? Perhaps we can improve it.

replies(2): >>wakawa+mB >>swaits+j62
◧◩
6. wakawa+mB[view] [source] [discussion] 2025-12-06 06:48:56
>>martin+wz
>Like what? Perhaps we can improve it.

I'm sure it is stuff that makes sense to a jj user. Since I have not read the manual, it is nonsense to me. I'm just drawing attention to the fact it's a different set of non-obvious terminology and features as compared to git. I'm sure anyone who read the manual for either tool could figure it out. The trouble with git is that people don't read the manual, and hardly try to do anything with it, then loudly complain about it being tricky. Anything as complicated as version control is going to be tricky if you don't read the manual. I don't think making another tool entirely is the right solution. Perhaps a different set of git porcelain tools could help, or some git aliases. Maybe better documentation too. But some people just can't be pleased.

replies(1): >>martin+PC
◧◩◪◨
7. wakawa+2C[view] [source] [discussion] 2025-12-06 07:01:58
>>martin+2v
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.

replies(1): >>martin+bD
◧◩◪
8. martin+PC[view] [source] [discussion] 2025-12-06 07:14:56
>>wakawa+mB
This seems to be a common misconception, that many jj users don't understand Git. Most jj users I know were pretty good at Git as far as I can tell. Perhaps you'll find this recent video where Scott Chacon talks about Jujutsu interesting: https://www.youtube.com/watch?v=PsiXflgIC8Q. Scott is a GitHub cofounder, author of Pro Git, and now runs GitButler.

> I don't think making another tool entirely is the right solution.

I considered making the changes to Git but the changes I wanted to make would make the UX so different that it would basically mean introducing a whole parallel command set to Git. I figured it would take ages to get Git to that state, if I could sell the ideas to the Git community at all. By the way, the video above talks about an proposed `git history` series of commands inspired by Jujutsu (also see https://lore.kernel.org/git/20250819-b4-pks-history-builtin-...).

replies(1): >>wakawa+Ld1
◧◩◪◨⬒
9. martin+bD[view] [source] [discussion] 2025-12-06 07:20:55
>>wakawa+2C
> 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).

replies(2): >>wakawa+Pa1 >>171862+Qy1
◧◩◪◨⬒⬓
10. wakawa+Pa1[view] [source] [discussion] 2025-12-06 14:08:04
>>martin+bD
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.
◧◩◪◨
11. wakawa+Ld1[view] [source] [discussion] 2025-12-06 14:35:47
>>martin+PC
Well, if I had to guess, many current jj users are git veterans who are tired of watching git noobs struggle. The other segment is the git noobs themselves, who never really bothered to learn git and have a deep aversion to reading the manual and doing basic experiments. Just a guess, though.

I think I saw Scott Chacon talk about his git config file and advanced git features. Whoever it was, it mentioned GitButler. That was a good talk. I would certainly expect someone like that to have a lot of interest and expertise in git. But it seem to me that there is also a potential commercial angle to making a new/alternative VCS.

I looked at the mailing list entry you linked to about `git history` commands and thought to myself, it sounds all wrong and redundant. `git history` sounds like too broad of a name for one thing. I'd want to have it be `git <verb>` instead. All the operations listed can be done with rebase:

- `git history drop`: Instead, rebase interactively and drop one or more commits.

- `git history reorder`: Interactively rebasing makes this work already.

- `git history split`: Insert a pause in the interactive rebase. Do a soft reset or something to the previous commit, and use `git restore` to unstage the changes (there might be a more efficient way to do this in one step, but idk). Then, do `git add -p` to add what you want, commit, as many times as you want to split the patch. Then continue the rebase.

- `git history reword`: There is a reword option in interactive rebase mode, and also a fixup-like option to do it as well if you want to postpone the rebase.

- `git history squash`: Rebase can do this now in multiple ways.

Rebasing is not that hard. It is the Swiss Army knife of VCS tools. Once you realize that you can just break in the middle of a rebase and do nearly anything (except start another rebase), the world is your oyster. We don't need to spam people with many more single-purpose tools. We need people to understand why the way things are is actually pretty damn good already, if only they read the manual.

replies(1): >>martin+Ae1
◧◩◪◨⬒
12. martin+Ae1[view] [source] [discussion] 2025-12-06 14:43:09
>>wakawa+Ld1
The author of `git history` is a GitLab employee and prolific Git contributor. I think he knows how `git rebase` works.
replies(2): >>wakawa+jn1 >>171862+Xz1
◧◩◪◨⬒⬓
13. wakawa+jn1[view] [source] [discussion] 2025-12-06 15:53:44
>>martin+Ae1
That makes his decisions all the worse and in poor taste IMO, because he ought to know that these use cases are well-covered already. Furthermore, I'm not talking to him. I'm talking to anyone who thinks that his patch was a good idea. I am not going to be dazzled by brand names in this conversation lol.
◧◩◪◨⬒⬓
14. 171862+Qy1[view] [source] [discussion] 2025-12-06 17:25:37
>>martin+bD
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.

replies(2): >>martin+EB1 >>wakawa+n52
◧◩◪◨⬒⬓
15. 171862+Xz1[view] [source] [discussion] 2025-12-06 17:33:16
>>martin+Ae1
I think the issue that wakawaka28 has and I also have is, that I don't think we should have lots of "wizards" for specific high-level operations users want to do. Then we will only end up with hundreds of commands, that all do slightly the same. Also it will train (new) users to complain about adding yet another command to do what they want, instead of letting them learn how to combine the already existing commands.

What we should do instead is provide a bunch of primitives, that as high-level are as possible so to not end up with duplicate commands, which is what git does currently. `git history` as a name is somewhat pointless, since the whole point of git is to produce and modify the history. In that sense `git history` already exists, it is called `git`.

I think the issue newbies have is not that git commands are hard per se, but that they don't think in terms of modifying the graph yet, or that they don't know which primitives are available.

replies(1): >>stevek+uO1
◧◩◪◨⬒⬓⬔
16. martin+EB1[view] [source] [discussion] 2025-12-06 17:45:59
>>171862+Qy1
Let's say you have this (modified from `git rebase --help`):

``` A---B---C main \ D---E---F feature1 \ \---G---H feature2 \ \---I---J feature3 ```

(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?

replies(2): >>171862+kE1 >>stevek+6O1
◧◩◪◨⬒⬓⬔⧯
17. 171862+kE1[view] [source] [discussion] 2025-12-06 18:11:57
>>martin+EB1
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.

◧◩◪
18. stevek+XN1[view] [source] [discussion] 2025-12-06 19:23:05
>>wakawa+gi
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.

◧◩◪◨⬒⬓⬔⧯
19. stevek+6O1[view] [source] [discussion] 2025-12-06 19:24:42
>>martin+EB1
Hacker News doesn't support Markdown, but you can indent lines by two spaces to get it formatted like code: https://news.ycombinator.com/formatdoc
◧◩◪◨⬒⬓⬔
20. stevek+uO1[view] [source] [discussion] 2025-12-06 19:26:58
>>171862+Xz1
For what it's worth, I mostly see jj as being to git what you describe in your first few paragraphs. That's why I like it so much.
◧◩◪◨⬒⬓⬔
21. wakawa+n52[view] [source] [discussion] 2025-12-06 22:05:26
>>171862+Qy1
>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.

replies(1): >>stevek+T82
◧◩
22. swaits+j62[view] [source] [discussion] 2025-12-06 22:14:56
>>martin+wz
This isn't going to be a very HN-like comment. But it's rooted in fact: That is complete nonsense.
◧◩◪◨⬒⬓⬔⧯
23. stevek+T82[view] [source] [discussion] 2025-12-06 22:35:05
>>wakawa+n52
jj doesn't force you to resolve the conflicts immediately, so it'll just show that they're conflicted until you decide you want to go fix them.
[go to top]