martinvonz / jj

A Git-compatible VCS that is both simple and powerful
https://martinvonz.github.io/jj/
Apache License 2.0
9.03k stars 314 forks source link

FR: when abandoning the working copy, use the same children for the new change #4468

Open samueltardieu opened 1 month ago

samueltardieu commented 1 month ago

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

After creating a fix-up commit in the middle of a tree and working on it, I squashed my changes into the parent commit because some more tests passed, but I still intended to continue working on the fix. However, the new commit created after jj squash didn't have the same children as I expected: I was now branching out of the tree instead of working in the middle of it.

Describe the solution you'd like

I would have liked my new commit to have the same children (same child in my case) as the one who just got emptied, so that I could continue working "at the same place" in the tree.

Describe alternatives you've considered

I could have used jj squash --keep-emptied, but I like the idea of abandoning a change when emptying it via squashing and starting a new one.

Additional context

The newly created change after abandoning the working copy keeps the same parents as the previous working copy. Also preserving the children would be more consistent.

Backward compatiblity concerns

The change would change the behavior of jj only in one particular scenario:

I think it is unlikely that a user would want to:

Care must be taken to ensure that a plain jj new, done while working in an empty change in the middle of the tree, do not preserve the same children, as in this case the goal is clearly to create a new head.

yuja commented 1 month ago

If we make new wc preserve the old children, we might also need to auto-abandon it. Otherwise, an empty wc commit would be left after squashed.

samueltardieu commented 1 month ago

If we make new wc preserve the old children, we might also need to auto-abandon it. Otherwise, an empty wc commit would be left after squashed.

I think this is the case with the patch I'm proposing, or I didn't understand your concern.

yuja commented 1 month ago

I assumed the workflow is jj new -A x && do some edit && jj squash && do another edit && jj squash && .... After the last jj squash, there will be an empty working-copy commit. If it's a head commit, it will be abandoned by checking out another commit. However, if it's inserted between x and x+, the empty commit will be left there.

samueltardieu commented 1 month ago

Good point. Indeed, this is currently not the case, as the user is in the same state as if they just used jj new -A x, checking out another commit will not abandon the empty one.

Or should we systematically abandon an empty wc commit when we checkout another one? It may disrupt other workflows, for example jj new -A x; jj edit y; jj squash --into x+ -i (for people who don't use jj new --no-edit).

samueltardieu commented 1 month ago

Another solution would be to make --keep-emptied more practical to use, for example by adding a short option (-k?). I mean, instead of the proposed change.

yuja commented 1 month ago

Or should we systematically abandon an empty wc commit when we checkout another one? It may disrupt other workflows, for example jj new -A x; jj edit y; jj squash --into x+ -i (for people who don't use jj new --no-edit).

True. I'm not sure if the current behavior makes sense. I rarely use editing workflow.

Anyway, if we make jj squash @ retain wc children, the rule should apply globally so jj abandon @ will recreate the same DAG structure. Then, it will probably make sense to auto-abandon non-head wc commits.

martinvonz commented 1 month ago

Btw, #4238 seems related. It suggests not ever implicitly creating a new working-copy commit. If we did that, then jj squash --keep-emptied would probably be what you would want (and maybe it is regardless).