jj icon indicating copy to clipboard operation
jj copied to clipboard

FR: Rename `jj rebase` to `jj move`

Open thomasa88 opened this issue 1 month ago • 20 comments

Is your feature request related to a problem? Please describe. The word "rebase" is about changing the base of something. For example, changing the "base" of a branch or a set of branches would intuitively mean to change their parent.

jj rebase sounds good when moving a change(s) onto another change(s), as it modifies their "base". However, jj rebase is much more versatile than changing the "base". It supports inserting changes after or before another change in the change history. The flag most closely related to rebase, --onto (previously --destination), can even be excluded in those cases.

I find "after" and "before" not as intuitively linked to rebase, although the insert prefix does make the semantics more coherent.

Describe the solution you'd like Change the name of the rebase command to move.

move should be more intuitive to new users, since it moves changes in the change graph.

The documentation for rebase even starts with (emphasis mine):

Move revisions to different parent(s)

This command moves revisions to different parent(s) while preserving the changes (diff) in the revisions.

Finally, move is shorter than rebase. (It could even have the shorthand mv.)

One might even consider dropping insert from --insert-after and --insert-before, as "before" and "after" sounds natural with "move".

move branch, move revisions.
move onto, move before, move after.

Describe alternatives you've considered Keeping rebase as is, as the command is familiar to many existing VCS users.

Git natively has rebase. Mercurial and Bazaar also have rebase available as extensions.

"moving (yourself) to a change" vs "moving a change (itself)" could be considered to close to each other and confusing for the user. jj edit moves the user to another change.

squash also "moves" things according to its help, making for another possible "move" collision:

Move changes from a revision into another revision

move is possibly not the best fit for "moving" a change onto multiple other changes (creating a merge). rebase sounds more correct in that case, in my opinion.

move might be associated with moving files. However, jj now has the file command/namespace for file operations.

Additional context There existed a move command in jj in the past, to move files between commits ( https://github.com/jj-vcs/jj/issues/7465 ).

Some arguments and examples pulled from https://discord.com/channels/968932220549103686/1446213639865630821 and conversations that it links to.

Please excuse any mix-ups of the words revision, change and commit.

thomasa88 avatar Dec 06 '25 19:12 thomasa88

In my mental model, there is too much muscle memory of OS commands and other VCS commands of "move" being about files and directories to have it mean something else. Not sure the specific reason that the old move was renamed, but I think it was a good thing...and I don't want to see it come back. As for the squash and split doing basically the same thing, and then rebasing descendants, I think that's why rebase is distinct from squash, so it can be applied separately, like after a fetch.

joyously avatar Dec 06 '25 21:12 joyously

relocate? More-or-less a synonym in this case, but avoids semantic confusion with other "move"s.

michaelpj avatar Dec 08 '25 11:12 michaelpj

In my mental model, there is too much muscle memory of OS commands and other VCS commands of "move" being about files and directories to have it mean something else.

I mean there's the whole jj file namespace just for files, so this issue is trivially solved by introducing a jj file move. Also the toplevel jj move can be interpreted as jj graph move since almost all jj operations work on it by default.

PhilipMetzger avatar Dec 08 '25 15:12 PhilipMetzger

Also the toplevel jj move can be interpreted as jj graph move

That's not the point. All of the other move commands came first, and are very ingrained. It was bad (to me) when jj had a move command, and I think renaming it was a good thing, and don't want to go backwards.

Side note: I think a VCS works on files, and having the default namespace for the commands be about the graph is putting more burden on the human than necessary.

joyously avatar Dec 08 '25 18:12 joyously

All of the other move commands came first, and are very ingrained. It was bad (to me) when jj had a move command, and I think renaming it was a good thing, and don't want to go backwards.

I mean we already deprecated and removed two very ingrained names, checkout and merge so I think it should be totally fine to do such a thing. Also this is not going backwards by making version control more accessible by not requiring knowledge about bases and what a rebase does.

PhilipMetzger avatar Dec 08 '25 18:12 PhilipMetzger

I think it's pretty fraught to reuse a common verb that other tools agreed on (move/mv). Off the top of my head, tools that had a move/mv command to rename files under source control management include Perforce, Subversion, Mercurial, Git (which doesn't even explicitly track renames!), Bazaar (and its heir Breezy), and Monotone (though there it was an alias for rename).

Ages ago I lobbied Martin (in chat, privately) to rename checkout so that the old verb didn't do something surprising - a missing verb is much better of a UX surprise than a verb which does something unexpected or confusing when compared to predecessor systems in the same space. I think the same thing applies here: everyone that's used git/hg already knows rebase and it's not really confusing, but anyone with experience in pre-jj systems is likely to be confused by a jj mv that does something in the revision space rather than the file space.

durin42 avatar Dec 09 '25 16:12 durin42

I agree with the desire to rename rebase to something else, for the reasons stated in the original proposal and also because in my experience most git users use rebase in one of two ways:

  1. (most common) git rebase -i
  2. (common) git rebase <destination branch>

Yes, there's lots of people that use the other forms of rebase, or that use --onto or whatever, but whenever I've had discussions with people -- including people that have worked on git itself for years -- when they say "rebase" aloud they mean git rebase -i. And in my mind, and maybe this is because I'm coming from more of a Mercurial background where that's spelled hg histedit, that's a very different operation from git rebase (without -i). Since jj doesn't really support the operation that git calls git rebase -i, if "rebase" == "rebase -i" to a significant portion of git users, then we should probably not index too heavily on git having a rebase command meaning we should too.

So I'm all for renaming jj rebase to be something else. I just don't like jj move as that new name, for all of the reasons stated already, so no need to repeat them, but also an additional one: if we name it jj move, would we rename jj duplicate to be jj copy? If not, then does the reason why we wouldn't do that apply to arguing against jj move as the name for this operation?

I like @michaelpj 's suggestion of jj relocate, fwiw.

spectral54 avatar Dec 09 '25 20:12 spectral54

My issue with relocate is that I think it is harder to write than rebase. I agree that it is interchangable with move with regards to the meaning in this context.

thomasa88 avatar Dec 10 '25 06:12 thomasa88

Mercurial has an hg graft command with similar functionality (it overlaps with its hg rebase command). I don't know if that's a better name, but I wanted to mention it just in case.

I don't feel strongly about renaming rebase to move or something else or not renaming it. But I'm not sure that jj move will be that confusing because users who run jj move file1 file2 hoping that it will rename the file will probably realize very quickly that it was the wrong command. We can even make that print a hint and/or mention jj file move in jj move --help. If we don't have a real jj move command for renaming files (or for rebasing), then we can still have some stub command that just hints about jj file move. That is, perhaps we want to make jj hint file1 file2 hint about jj file move regardless. Again, I don't feel strongly about renaming the command either - I think people are so used to it being called rebase by now that it's fine. A better name would be mostly about making it slightly easier for a new generation of VCS users IMO.

martinvonz avatar Dec 10 '25 07:12 martinvonz

We can even make that print a hint and/or mention jj file move in jj move --help

I'm vaguely in favor of moving to move, but I want to mention this pattern is very powerful, in general. In Rust, for example, we made the compiler parse await foo and print out a "hey, you want foo.await" message, which really alleviated a lot of the "well what if someone does the wrong thing due to knowing other languages" concerns.

steveklabnik avatar Dec 11 '25 20:12 steveklabnik

I note that jj already has a lot of top-level verbs that could be confusing if you don't realise they're referring to revisions: new, edit etc. So I don't think it's that unreasonable to expect users to get the message that top level commands work on revisions, and so the same is true of jj move . If anything it's nice and consistent!

michaelpj avatar Dec 11 '25 22:12 michaelpj

Personally I would also prefer copy to duplicate as well!

michaelpj avatar Dec 11 '25 22:12 michaelpj

I note that jj already has a lot of top-level verbs that could be confusing if you don't realise they're referring to revisions: new, edit etc.

I think that's a reason to fix all the confusing ones, not to make more.

Would a rename propagate through the documentation too? So where a flag is explained as:

When rebasing a descendant on top of the rewritten revision, its diff compared to its parent(s) is normally preserved, i.e. the same way that descendants are always rebased.

or an example is given:

If the previous version has different parents, it will be temporarily rebased to the parents of the new version, so the diff is not contaminated by unrelated changes.

The explanations have to make sense with the changed name.

joyously avatar Dec 12 '25 00:12 joyously

If you ignore p4 I think both new and edit are previously-unused verbs in past VCS tools. That's important because it means they'll invite curiosity and not be encountered with surprise when they do something unexpected.

durin42 avatar Dec 12 '25 02:12 durin42

I think it would be nice and consistent if all of these commands existed:

  • move
  • copy
  • edit
  • new
  • file move
  • file copy
  • file edit
  • file new

I think having a consistent set of verbs that act on different nouns invites less cognitive load and confusion than having to remember which of several synonymous verbs are paired with each noun. Just like how it’s good to have consistent flags that work across different commands.

amonks avatar Dec 12 '25 08:12 amonks

I've been thinking deeply about the name "rebase" for a while, as it happens. Coming from a git background, so I will use the terms "commit" and "delta" so as not to accidentally confuse myself & everyone. Apologies if I've missed something fundamental about jj and this is a waste of time.

I think the main problem with "rebase" is that newcomers to vcs have long-lasting trouble figuring out what it means. And yet it's such an important verb of the system.

The second biggest problem with rebase, which seems natural to me now but is a source of perpetual newcomer mystery & footguns, and which is relevant to trying to name it "move", is that it actually moves deltas, not commits. (Git will even try to linearize the resulting history, by default!) If you think about it like moving commits around the DAG, you are wrong, and you will not understand why you are getting conflicts, or really what you are doing at all. Due to this, as a veteran git user, "rebase" is lexicalized in my brain as something like "replay the deltas on a new base", although that's not self-explanatory at all. That's not to defend the name "rebase". I think maybe a better name for this feature would be something like apply-deltas (I actually think delt would be a great verb for it, but I have a perhaps-foolish taste in words). In fact, git-rebase's man page currently reads git-rebase - Reapply commits [sic]on top of another base tip[sic].

An aside: I am also looking for a way to do the opposite, to really move the unchanging (except for metadata) commits around the DAG, to change the parent IDs and nothing else. I would call this "reparent", I think, but no such thing seems to truly exist.

jj duplicate seems to have already started down the road of conflating delta and commit operations, with an even more suggestive name. I think this is one of the stumbling blocks of revision control systems and it doesn't seem like a great choice to me. (Seems like you could also call that one apply-delta.) To be fair, I guess the fact that we write commit messages like they are delta messages — and, indeed, store the parent ID in the child commit itself for such easy diffing — already starts this conflation.

Incidentally, git already has a mv subcommand. I take it jj doesn't need this because the current commit is already aware of the working tree so you don't need to tell git to move a file as well. Nice. My (obscure) Gyatt suite also has a move subcommand, which moves the current branch tip somewhere (the "move (yourself)" interpretation) — and which I had planned to make move other branches if supplied, but I never got around to that. Jj also doesn't need this because it just uses jj bookmark move, I hear. I say all of this to note that git has used move before, but in a radically different, so I wouldn't really worry about that. (Although I should have worried about it when I made my git aliases, probably.)

So, in conclusion, I think "rebase" is a useless term, and "move" is better but implies the wrong mental model. Something like "apply deltas" would be better. jj delta move?

wyattscarpenter avatar Dec 12 '25 09:12 wyattscarpenter

If you think about it like moving commits around the DAG, you are wrong, and you will not understand why you are getting conflicts, or really what you are doing at all.

I think my recent discussion is exactly what you are referring to. The user shouldn't have to know the implementation details, and since we are talking about a top level command, it isn't about Git at all (other backends exist). The command names (and docs) should lead the user to a consistent mental model, and the user should only be concerned with files and changes and times and authors, not deltas or diffs or commits or snapshots or graphs.

joyously avatar Dec 12 '25 15:12 joyously

@durin42

I think it's pretty fraught to reuse a common verb that other tools agreed on (move/mv). Off the top of my head, tools that had a move/mv command to rename files under source control management include Perforce, Subversion, Mercurial, Git (which doesn't even explicitly track renames!), Bazaar (and its heir Breezy), and Monotone (though there it was an alias for rename).

I generally disagree with this framing because jj actually already made a bunch of decisions which differentiates it from all its predecessors (and I think constraining it by decisions made 30 years ago and not re-evaluating them is a bad idea). It may be unfamiliar and scary to current users and or Fig/Mercurial and Git converts but it is straight up better for the next generation of VCS users, and I think that the first group will easily adjust to that. (I also wouldn't ship a mv alias by default, since unixism's require Unix knowledge which is something someone new to VCS and programming will not understand).

Ages ago I lobbied Martin (in chat, privately) to rename checkout so that the old verb didn't do something surprising - a missing verb is much better of a UX surprise than a verb which does something unexpected or confusing when compared to predecessor systems in the same space. I think the same thing applies here: everyone that's used git/hg already knows rebase and it's not really confusing, but anyone with experience in pre-jj systems is likely to be confused by a jj mv that does something in the revision space rather than the file space.

I also very much disagree with this stance, since something which isn't supported or actually matches a previous understanding of a verb shouldn't exist to smoothen the curve. As someone who out found your stance and discussion with Martin post-checkout deprecation with an extremely bad game of telephone, that this deserved to be openly communicated.

@spectral54

but also an additional one: if we name it jj move, would we rename jj duplicate to be jj copy? If not, then does the reason why we wouldn't do that apply to arguing against jj move as the name for this operation?

I consider duplicate a good name, but if someone is convinced enough that it should be copy nothing stops them for proposing it, although that will need to be a separate discussion.

PhilipMetzger avatar Dec 12 '25 17:12 PhilipMetzger

The second biggest problem with rebase, which seems natural to me now but is a source of perpetual newcomer mystery & footguns, and which is relevant to trying to name it "move", is that it actually moves deltas, not commits. [...] If you think about it like moving commits around the DAG, you are wrong, and you will not understand why you are getting conflicts, or really what you are doing at all.

In my mind, one moves "changes" (change IDs) in jj when doing rebase. When I use jj rebase -r xyz::xxx -B yyy I see xyz::xxx move in the graph. The change IDs stay the same. Sure, the commit IDs change, but I seem them more as non-important side data.

In git, the primary ID is the commit ID, and the primary ID changes when rebasing.

thomasa88 avatar Dec 12 '25 19:12 thomasa88

@joyously I don't think what I'm discussing is an implementation detail or particular to git. The difference between (revisions) and (differences between revisions) is inevitably important in this domain.

@thomasa88 that's true, but I'm not sure whether or not that helps. After all, the delta that the Change ID corresponds to will (often) be different after rebasing. The contents of the files in the revision the Change ID corresponds to will (often) also be different. Some metadata will be the same, like the Change ID and the commit message. But maybe the "change" mental model makes all of these guarantees and non-guarantees clear enough to the user that there is no problem. It is at least true, in any case, that it would be accurate to call or describe the action under consideration "moving changes", if one understood the details of what "moving" here entails.

wyattscarpenter avatar Dec 12 '25 20:12 wyattscarpenter