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: Working copy stack #3713

Open
buildwithzephyr opened this issue May 19, 2024 · 4 comments
Open

FR: Working copy stack #3713

buildwithzephyr opened this issue May 19, 2024 · 4 comments
Labels
enhancement New feature or request

Comments

@buildwithzephyr
Copy link

buildwithzephyr commented May 19, 2024

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

One thing that JJ makes really easy is going back in your history and editing previous changes. I often find myself doing something like this:

  1. jj edit or jj new <rev>
  2. Make some changes and then jj squash.
  3. Move back to the (now automatically rebased) descendant change that I had been working on.

A frustration here is that in order to do step 2, I have to know the (short-form) change id, usually by searching in jj log.

Describe the solution you'd like

I think that an elegant solution to this problem would be to have a "working copy stack," analogous to the directory stack in most shells. In particular,

  1. Any command which explicitly changes the working copy - such as jj new <rev>, jj edit <rev>, or jj split -r <rev> - would push to the working copy stack.
  2. However, a command which simply advances the working copy by one - such as jj commit, jj next and jj prev, or jj new with no arguments - would instead just update the top of the working copy stack. (analogous to cd instead of pushd)
  3. There would be a command to pop the top of the working stack, and also one to list the working copy stack so that you can easily find previous working copies without digging through the log. One possibility is jj wc with subcommands pop and list.
    • There could also be a subcommand called push or new. This would duplicate the top of the stack, so that you can go back to it if your next command is about to overwrite the top of the stack.

The workflow above would now look like...

  1. jj edit or etc. and make some changes.
  2. jj wc pop and you're back where you were.

Because it's a stack that updates every time you manually change your working copy, it could just be generally useful whenever you're working with multiple branches or lines of work (whether or not you are tracking them as branches in Git.) I can imagine lots of scenarios where jj wc list would be very helpful to have.

Describe alternatives you've considered

This is related to #2871. It solves a lot of the same problems. However, the proposed solution is different in that it has a stack as opposed to just a history, and in that the user doesn't have to deal with revsets - which I think would make it more approachable to beginners or to people like me who are coming from Git. The two solutions could be compatible; one could implement a revset function that lists the working copy stack.

Additional context

How long to keep the stack around is an open question - do you want things in the stack from months ago? Certainly a jj wc clear would be a good thing to have.

@PhilipMetzger
Copy link
Collaborator

This can also be solved with a history topic which represents your stack, see #3402. It'd be less invasive too.

@PhilipMetzger PhilipMetzger added the enhancement New feature or request label May 19, 2024
@martinvonz
Copy link
Member

For the first use case mentioned above, you can do something like jj new 'heads(@-:: ~ @)'. You can define an alias for that and/or define a revset alias for the revset.

@arxanas
Copy link
Collaborator

arxanas commented May 26, 2024

In Git, their stack-like data structure (git stash) interacts very poorly with the rest of the system because it doesn't use the same vocabulary or mechanisms. Similarly, I think creating a dedicated working-copy stack command in jj (not the same as git stash) would interact poorly with the rest of jj. If we implement this, rather than a dedicated command, I think we should make more revsets, so that you can address+manipulate those commits by the standard means.

I think it doesn't currently, but if the operation log were to store the command/subcommand that was invoked for each operation, then you might be able to implement this yourself today without special jj integration.

@cormacrelf
Copy link
Collaborator

I think that an elegant solution to this problem would be to have a "working copy stack," analogous to the directory stack in most shells.

@arxanas: If we implement this, rather than a dedicated command, I think we should make more revsets, so that you can address+manipulate those commits by the standard means.

This popped out immediately for me:

jj new -

Same as cd -. - on its own would be a revset referring to the parents of the previous @. And you could add a few enhancements to the revset parser to make -- mean the second last instead of being equivalent to (-)-.

I think it would also behave differently depending on whether you reached your previous working copy by calling jj new or jj edit.

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

5 participants