Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Goal

You learn to copy/paste from one Change to another.

Copying Files

Good things always come in threes. You have met jj squash and jj rebase; meet jj restore. All for one and one for all: together those three musketeers are all you need to bend the history tree to your will:

OperationCommand
Move a Change somewhere elserebase
Move the changes you made somewhere elsesquash
Copy files from one Change to anotherrestore

jj restore is a command for copying file contents, and it shares the same syntax as jj squash (have I already told you that Jujutsu is consistent?)

jj restore -f FROM -t TO FILES

This would copy the content of FILES from FROM to TO.
Think of it as copy-paste: you copy the content of FILES from FROM and paste them into TO. The original in FROM stays unmodified.
This includes deletions: if a file was deleted in FROM, it will be deleted in TO too.

As for squash, if you omit either -f or -t, the Current Change @ will be implied.
If you omit FILES, the whole working copy will be restored.

When Is It Useful?

Days ago your README.md had rich examples and beautiful ASCII diagrams. Then your PM asked for something "more executive". Fine, you trimmed it down. PMs are always right. Especially on Friday afternoon.

Today the same PM says (because of course they do): "You know what? Actually, I liked the long version better".

You sigh and call jj restore to the rescue:

  • You jj log and find the Change X with message docs: README with beautiful diagrams
  • jj restore --from X README.md

Done.
You see? You are not "going back in time": you are pulling a file out of an old snapshot and pasting it into the Current Change.

Is This Use Case Really That Common?

Not particularly. But like with jj squash, there are interesting consequences to the jj restore's default arguments.