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

Make jj squash --from accept multiple commits #3276

Merged
merged 3 commits into from
Mar 13, 2024
Merged

Conversation

martinvonz
Copy link
Member

@martinvonz martinvonz commented Mar 12, 2024

Closes #2678

Checklist

If applicable:

  • I have updated CHANGELOG.md
  • I have updated the documentation (README.md, docs/, demos/)
  • I have updated the config schema (cli/src/config-schema.json)
  • I have added tests to cover my changes

cli/src/description_util.rs Outdated Show resolved Hide resolved
cli/src/commands/squash.rs Outdated Show resolved Hide resolved
cli/src/commands/squash.rs Outdated Show resolved Hide resolved
cli/src/commands/squash.rs Outdated Show resolved Hide resolved
cli/src/commands/squash.rs Show resolved Hide resolved
cli/src/description_util.rs Show resolved Hide resolved
cli/tests/test_squash_command.rs Show resolved Hide resolved
I'm going to teach the function to support combining more than two
descriptions.
@martinvonz martinvonz force-pushed the push-knpoklsnrqtx branch 2 times, most recently from 29f8620 to fa5eaa0 Compare March 13, 2024 05:11
Copy link
Collaborator

@yuja yuja left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm, thanks.

cli/src/commands/squash.rs Outdated Show resolved Hide resolved
cli/src/description_util.rs Outdated Show resolved Hide resolved
… sources

I plan to teach `jj squash --from` to accept a revset as input.
Now you can do e.g. `jj squash --from 'foo+::' --into foo` to squash a
whole series into one commit. It doesn't need to be linear; you can
squash a bunch of siblings into another siblings, for example.
@martinvonz martinvonz enabled auto-merge (rebase) March 13, 2024 12:12
@martinvonz martinvonz merged commit 800f0f0 into main Mar 13, 2024
16 checks passed
@martinvonz martinvonz deleted the push-knpoklsnrqtx branch March 13, 2024 12:21
@@ -105,8 +105,7 @@ aborted.
// case).
if new_parent_tree_id == parent_base_tree.id() {
tx.mut_repo().record_abandoned_commit(parent.id().clone());
let description =
combine_messages(tx.base_repo(), parent, &commit, command.settings(), true)?;
let description = combine_messages(tx.base_repo(), &[parent], &commit, command.settings())?;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is unsquash simply split?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, jj squash -r X moves from X into its parent (by default), while jj unsquash -r X moves from the parent into X.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does that relate to split?
Or are you saying the squash action is on the graph and not the content?
(It's really difficult to determine what affects just the graph and what affects the content.)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

split takes a single commit and splits it in two, while squash and unsquash move changes between existing commits (and it removes commits that became empty).

@emesterhazy
Copy link
Collaborator

Did you consider using --source and --destination for consistency with jj rebase? For what it's worth, the first time I tied to use jj squash --from I did it wrong because I assumed it would squash everything between the --from revision and @ or --into. I feel like --source would make it a little clearer that I need to write a revset expression if I want to squash multiple commits.

Perhaps we could also improve the --help page. The --from argument is allowed to resolve to multiple revisions, but the --into argument is not. Despite this their documentation is nearly identical.

@Zambito1
Copy link

Zambito1 commented Apr 2, 2024

Related to @emesterhazy's comment, I did not find it immediately obvious that --from accepts a revset from its description on jj squash -h:

--from <FROM>          Revision to squash from (default: @)

Maybe describing this as Revset to squash from would be better

@Zambito1
Copy link

Zambito1 commented Apr 2, 2024

jj diff also uses --from to essentially mark the start of a revset, reinforcing that expectation for that behavior in squash. --source and --destination would also make more sense to me.

@martinvonz
Copy link
Member Author

Did you consider using --source and --destination for consistency with jj rebase?

They mean something different for jj rebase, though. --source includes descendants, and --destination indicates a commit to add new commits on top of. I was worried the difference would make it confusing but maybe it's not.

@yuja
Copy link
Collaborator

yuja commented Apr 3, 2024

Did you consider using --source and --destination for consistency with jj rebase?

They mean something different for jj rebase, though. --source includes descendants,

I agree about this. squash --from is closer to rebase -r, but squash -r would be more confusing.

and --destination indicates a commit to add new commits on top of.

I'm not too worried about this point, maybe because "squash" implies the destination is mutated.

@emesterhazy
Copy link
Collaborator

They mean something different for jj rebase

Hmm, I didn't think of that. Personally I think the semantics for squash are clear enough that -s and -d wouldn't be confusing, but I see your point. It does seem a little odd though that --from will happily accept a union of two change IDs but it can't be specified multiple times the way -s can for rebase. This seems like an artificial limitation but maybe there's a case I'm overlooking.

If we keep the current names I think we should clarify the description of --from though, and maybe it should be repeatable.

@martinvonz
Copy link
Member Author

Did you consider using --source and --destination for consistency with jj rebase?

I forgot to say that jj move had --from and --to for consistency with jj diff/interdiff. I changed it to --into when copying the functionality to jj squash because I felt like it was clearer about the direction. I think we should also keep this consistency in mind if we decide to rename to -s/-d (i.e., should it be jj diff/interdiff -s/-d?).

@Zambito1
Copy link

Zambito1 commented Apr 3, 2024

FWIW

GitHub diff uses: base and compare

GitLab diff uses: source and target

It may be worth considering the terms these and other forges (perhaps even non git ones) use for this. I am particularly fond of the GitLab terms here.

@emesterhazy
Copy link
Collaborator

emesterhazy commented Apr 20, 2024

I think part of my opposition to --from is that it doesn't behave the way I'd expect. For diff, --from x appears to include the changes from @..x. It's a range and can be read as "all of the commits from @ to x".

But for squash, --from doesn't mean this and only a single revision is squashed.

I would propose the following:

  1. For squash, rename --from to --source/-s and --into to --destination/-d.
  2. For interdiff, rename --from to --source/-s and --into to --destination/-d. Since interdiff is described as temporarily rebasing --from onto --to, it makes sense to use the same flags as rebase.
  3. For diff, keep --from and --to since they do something that seems pretty different than what they do in the other commands (i.e. act on a range of commits) between the arguments.

I think this will be more logically consistent and ergonomic since we'll have short flags -s and -d for squash. Currently I find myself using prev --edit and edit xyx to position @ before squashing instead of typing out --from and --into multiple times.

@martinvonz
Copy link
Member Author

I think part of my opposition to --from is that it doesn't behave the way I'd expect. For diff, --from x appears to include the changes from @..x. It's a range and can be read as "all of the commits from @ to x".

We have had similar discussions before. I'm not sure what to search for to find those discussions, unfortunately.

Btw, another example is that diff -r should perhaps be renamed to diff -s too then since it works with the diff compared to the parent. Or maybe not since there's no destination argument?

@martinvonz
Copy link
Member Author

Oh, I also meant to say that I don't feel very strongly either way, so don't think that I'm ignoring you because I disagree; I'm just hoping that others will share their thoughts if they feel strongly.

@emesterhazy
Copy link
Collaborator

Yeah, this is just a proposal and not urgent. There are a few people subscribed to comments on this PR, but if nobody chimes in I can open a PR with these changes to collect comments.

I think that in my opinion -r is fine when there isn't a corresponding destination flag.

@yuja
Copy link
Collaborator

yuja commented Apr 24, 2024

another example is that diff -r should perhaps be renamed to diff -s too then since it works with the diff compared to the parent.

I think -r is okay here because it specifies a commit to be diffed (just like rebase -r specifies commits to be rebased.) We could rename it to --change (as in hg), but the word "change" is also overloaded.

To me, both --source and --from specify one end of a range or subtree.

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

Successfully merging this pull request may close these issues.

FR: Allow jj squash to span multiple commits.
5 participants