Skip to content
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

FR: Make jj squash -r take multiple revisions #5301

Open
martinvonz opened this issue Jan 8, 2025 · 1 comment
Open

FR: Make jj squash -r take multiple revisions #5301

martinvonz opened this issue Jan 8, 2025 · 1 comment
Labels
enhancement New feature or request

Comments

@martinvonz
Copy link
Member

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

I think it's natural to expect that jj squash -r <revset> squashes all the revisions in the given revset, but it currently accepts only one revision and squashes it into its parent.

Describe the solution you'd like

Allow more than one revision to jj squash -r and squash them all together. Passing a single revision would become a no-op. We should make that a warning for a while so existing users learn about the new behavior.

I think we can also allow non-contiguous revisions, similar to how jj parallelize allows non-contiguous revisions. Consider this history:

○  I
│ ○  H
├─╯
○  G
○  F
├─╮
│ ○  E
│ ○  D
○ │  C
○ │  B
├─╯
○  A

jj squash -r 'B|C|D|E' would separately squash {B and C} and {D and E}.

jj squash -r 'E|F' would squash E and F since they're directly related. The resulting commit would have C and D as parents, not just D. That's because F depends on the changes in both C and E before squashing, so the result should still depend on C. Squashing can therefore be seen as happening towards the children. That might also mean that the squashed revision's change id should be inherited from F.

If we allow jj squash -r 'G|H|I' and make it squash all three commits, it would mean that jj squash -r` could result in new conflicts (because we would combine the changes from H and I). It's also unclear which change id to use in this case. We would presumably either use G's change id or pick and arbitrary one between H and I. An alternative is to make that invocation squash G into both H and I (duplicating the changes from G), but that seems less useful, and probably not what the user intended.

Describe alternatives you've considered

Keep the current behavior, or extend it to allow multiple commits but squash them all into their parent(s). However, it seems surprising if jj squash -r A::C squashes the commits into A's parent(s).

Additional context

I think the reason I made jj squash -r originally take only a single revision and made it squash the changes into the parent is that it makes the default behavior of jj squash to be jj squash -r @. We'll have to change it to mean jj squash --from @ --to @-.

@arxanas
Copy link
Contributor

arxanas commented Jan 8, 2025

I could also imagine some workflows where you want to duplicate the input revisions rather then rewrite them. It would probably be fine to require you to run jj duplicate followed by jj squash, except that there's no straightforward way to automatically get the resulting duplicated commits and pipe them into jj squash. This is tracked by #3814.

I think we can also allow non-contiguous revisions, similar to how jj parallelize allows non-contiguous revisions.

[aside] Given that characterization, I added "squash" as a topology to my categorization in #4708 (where jj parallelize is described as a "horizontal" topology).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants