jj
jj copied to clipboard
FR: cli option consistency
Is your feature request related to a problem? Please describe.
a lot of jj commands do something to two different revisions, but it is very hard to remember how to do this because there are quite a few different ways that different commands specify them (for instance, from a quick browse of the manual, jj restore uses --from/--to, jj squash uses --from/--into, jj backout uses --revisions/--destination, and jj rebase uses --source/--destination).
additionally, for commands that act on a single revision, it's pretty split between whether that revision must be passed as a plain arg or through --revision.
currently i have to look up the correct option names in either the manual or my shell history pretty much every time i run one of these commands, which doesn't feel great.
Describe the solution you'd like it'd be really helpful to standardize on a single way to refer to the commits that operations will act on. i don't really have a preference other than that it'd be great if it could be more consistent across different commands.
- There are several semantic differences between the option names, in such a way that they are meant to be consistent, but I forget the nuances.
- For example,
jj rebase -r Xexists and i is different fromjj rebase -s, but generally consistent with other-rcommands. (It's roughly the same asjj rebase -r 'X::'?)
- For example,
- I believe that every command which takes a positional revision argument also accepts it via
-rfor redundancy; file a bug if not.- For example, you can write
jj new -r Xto mean the same asjj new X.
- For example, you can write
Funny timing with #5394 from less than a day ago. As @arxanas said, there are semantic differences between some of them.
additionally, for commands that act on a single revision, it's pretty split between whether that revision must be passed as a plain arg or through
--revision.
The reason is that we currently prefer to let positional arguments mean paths. So commands that accept paths (either currently or conceivably) require the revision to be passed via -r. We have #2554 and #3809 about that.
- For example, you can write
jj new -r Xto mean the same asjj new X.
That's actually an interesting case. I feel like it should accept -d but not -r because it creates the new commit on top of the argument. We talked about this on Discord a while ago. EDIT: We actually allow -d already.
i can see --to and --into having different meanings (although it's still hard for me to remember) but what is the intended difference between --from/--source and --to/--destination? i don't really have a good sense of what these semantic differences are supposed to be, and i can't find anything written about it. can you point me to somewhere that describes it?
also, the docs for jj rebase say that -r only rebases the one specific commit - were you thinking of -b or am i confused?
also, if it is intended that -r works everywhere, at the very least the documentation doesn't give any indication of this (for instance, jj abandon and jj describe don't mention -r at all).
--destination is when you are putting commits on top of an existing commit (e.g. rebase, new, backout, duplicate). --into is when you are modifying the commit itself. It’s about identifying the commit to modify vs. identifying “gaps” to fill in in the commit graph. I personally find that distinction intuitive and appreciate it; OTOH --to vs. --into is a bit of a mess (in part because it’s not clear what the --from corresponding to --into should be; --out-of is the best proposal I’ve heard, but it’s long).
jj rebase -r can take a multi‐commit revset these days. I think the documentation is out of date.
Edit: And --source identifies an entire tree of commits by its base (e.g. jj rebase -s BASE-OF-STACK -d 'main()'); I admit this name isn’t good but can’t immediately think of a better one. I believe that jj rebase -s X is the same as jj rebase -r X::, but I may be wrong.
i don't really have a good sense of what these semantic differences are supposed to be, and i can't find anything written about it. can you point me to somewhere that describes it?
We don't have such documentation yet. I suppose we could write some new doc about the CLI design philosophy in general. A less general but quicker solution would be to add an FAQ item or two.
jj rebase -rcan take a multi‐commit revset these days. I think the documentation is out of date.
Yes. I'll try to send a patch for that.
I believe that
jj rebase -s Xis the same asjj rebase -r X::, but I may be wrong.
You're not.
I believe that
jj rebase -s Xis the same asjj rebase -r X::, but I may be wrong.You're not.
But only assuming X is a single commit. If X is multiple commits, then jj rebase -s X will rebase each commit in the set onto the destination, while jj rebase -r X:: will preserve internal dependencies in the set.
See if https://github.com/jj-vcs/jj/pull/5400 helps clarify how the rebase flags work.
Another little case of possible inconsistency is jj backout.
I might be wrong, but I think the English phrasal verb is "back out, not backout, so the command should be jj back-out, with a separating dash just like in jj simplify-parents. The same could probably apply to jj interdiff`.
Anyway, given the fact that jj backout's manual states:
Apply the reverse of a revision on top of another revision
I don't get why the command is not simply jj reverse.
I think it's backout because of Mercurial heritage. I would prefer revert, which seems equally accurate and less awkward.
revert is confusing for hg users (hg revert is jj restore). We could still use that, or we could use reverse. Another option is rollback (or roll-back to be more grammatically correct).
Started a separate issue, specifically related to jj backout @ https://github.com/jj-vcs/jj/issues/5688 for anyone interested in discussing in more detail!
I am still learning (and loving) jj, so I'm far from being fluent. On the contrary, I'm that sweet point in time where I am sensitive to what is intuitive vs what is not. When I will be eventually fluent with it, I will just get used to inconsistencies and I won't see them anymore.
So far, as a completely noob, I can only second @doy's observation: moving back and forth from jj restore to other commands, I find myself consulting over and over the man pages and the shell history to figure out when to use -f/-t, when -r, when -t.
I am sure I will develop an intuition on the logic. Either
- more consistency
- or a little section in the manual explaining the rule of thumb when to use what option
would improve my overall experience (which is amazing, anyway)
Thanks for your feedback. I feel like this feature request has too large scope. It might be more productive to file separate feature requests for each concrete suggestion instead.
As others have said, CLI arg inconsistency gets confusing. Some quick suggestions:
- Always interpret
-ras a REVSET not a REVISION. Further to this, deprecaterebase --revisionsandsquash --revision(etc.) in favour of--revset. - The above might allow deprecating
squash --from,rebase --source. - Deprecate
-d/--destination,--to,--into. Use-t/--targetto replace all of these.
(I'm sure these suggestions are imperfect — don't have a lot of time to consider the implications.)
I found it odd that jj duplicate did not have the same -s and -b options that rebase had. This forced me to learn how revset language worked, where I didn't need to know that for rebase.