Skip to content

FR: Documentation / clarification around immutable_heads().. vs mutable() and x.. #6149

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
guibou opened this issue Mar 27, 2025 · 0 comments
Labels
documentation Improvements or additions to documentation

Comments

@guibou
Copy link

guibou commented Mar 27, 2025

Is your feature request related to a problem? Please describe.

Hello.

First of all, thank you for jj. I'm living my best developer experience since I abandoned hg and the evolve extensions years ago because git had won. And I even understanding git better since I'm using jj.

I had issues in order to understand the default jj log revsets:

present(@) | ancestors(immutable_heads().., 2) | trunk()

Especially, I had issue understanding why immutable_heads()... I've wrote some notes here: https://gist.github.com/guibou/0a8731e10dffe4919c987fc7bc263aea.

I was confused by the behavior of x..y operator. Even if the documentation is clear that it is "all parents of y including y which are not parent of x including x), there are two behaviors which were unclear or unintuitive (for me) at first sight:

  • x.. does not distribute on x. Said otherwise (A | B).. is NOT A.. | B... This had been counter intuitive for me
  • x..y is not a path between x and y. For example, with the following graph:
A - B - x - C
\ - D - y

There is no path between x and y. However x..y = {D, y} because there are ancestors of y but not ancestors of x. (Note that I had an "haha" moment here and discovered that it behaves the same as git actually, and I discovered that after 20 years of git)

These behavior are documented, but implicitly in the definition of the .. operator and examples:

* `B..` ⇒ `{D,C}` (note that, unlike `B::`, this includes `C`)
... 
* `B::D` ⇒ `{D,B}` (note that, unlike `B..D`, this includes `B` and excludes `C`)

Additionally to these confusion, I observed that:

  • immutable_heads(), the naming also confused me. It is not heads() which are immutable (e.g. immutable_heads() is not a subset of heads()). Instead it represents the heads() of the graph containing only the immutable revisions.
  • It is still unclear why immutable_heads().. is not instead written as mutable(). The difference is subtle (that's negation of :: and includes root(), but I had not been able to craft an example where they are both different.

Describe the solution you'd like

Improving the documentation, I'm unsure how unfortunately, That's a tradeoff between compactness and being explicit.

Maybe adding something like "Note that x..y is NOT limited to a direct path in the graph between x and y, see examples and that (x | y).. is not equal to x.. | y.. may just be enough to trigger the reader in order to force them to see and understand the examples.

Regarding immutable_heads, again, a line in the documentation saying that it is the head of the immutable revsets, and not the head() which are themself immutable.

Finally, It is unclear for my why immutable_heads().. is used in place of mutable(), so it is difficult for me to suggest a documentation improvement.

Thank you.

@PhilipMetzger PhilipMetzger added the documentation Improvements or additions to documentation label Mar 27, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

2 participants