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 find out how to travel your repository back in time, all the way when you cloned it.

The History Beneath the History

If every change has its own history, then your whole repository has its own history. It's only logical. Your repo:

  • In an initial stage (let's call it 000000000000) did not exist at all.
  • Then it was created.
  • Then you added a Change.
  • Then you edited a description.

and so on.

Jujutsu is stubborn, it remembers everything, since almost every command, including jj log, triggers a working-copy snapshot.

Inspect that meta-history with:

jj op log
  ○  3075743719f1 arialdo@mbuto default@ 19 minutes ago, lasted 22 milliseconds
  │  describe commit 22c5df185272af6f25b1d4227cd271971aa1baa5
  │  args: jj describe -r n -m baz
  ○  3daa0e64a476 arialdo@mbuto default@ 19 minutes ago, lasted 24 milliseconds
  │  describe commit 21a546e29d1cfcebdc0aafd8023c3d60416bff88
  │  args: jj describe -r n -m bar
  ○  4c7fc048be20 arialdo@mbuto default@ 19 minutes ago, lasted 23 milliseconds
  │  describe commit a857703785c7971ec20ccd826e36557f8b7d5a72
  │  args: jj describe -r n -m foo
  ○  a6df8a6d9206 arialdo@mbuto default@ 19 minutes ago, lasted 21 milliseconds
  │  describe commit 03e16e725052f4ba32bb0a1a31a029860a86519a
  │  args: jj describe -r n -m Foo
  ○  192c30f0cf47 arialdo@mbuto default@ 3 hours ago, lasted 5 milliseconds
  │  restore to operation 281b30d872a33f3dc6f93982343ab3fa4d2a4adb8b3bb4903421d84003d96e96e266d90bc4e6990526d8c5eea62423b19395d5f6d2639b6be26b77d301958274
  │  args: jj op restore '000000000000+++++'
  ○  2a2be2f2b8fc arialdo@mbuto default@ 3 hours ago, lasted 5 milliseconds
  │  restore to operation 8eea9aa811a1ed9ffd6e795d17573e77caad0ddf41c716489fbe8e7526aad797c10b2cbc4c45de0845b7e1f84c6a458f148e6eab9c1241fa72d7f62c1a2f89d3
  │  args: jj op restore '000000000000++++'
  ○  281b30d872a3 arialdo@mbuto default@ 3 hours ago, lasted 4 milliseconds
  │  remove git remote origin
  │  args: jj git remote remove origin
  ○  8eea9aa811a1 arialdo@mbuto default@ 3 hours ago, lasted 14 milliseconds
  │  check out git remote's branch: main
  │  args: jj git clone https://codeberg.org/arialdo/jj-playground1.git
  ○  eff465d67569 arialdo@mbuto default@ 3 hours ago, lasted 2 seconds
  │  fetch from git remote into empty repo
  │  args: jj git clone https://codeberg.org/arialdo/jj-playground1.git
  ○  ee32fa88d5f2 arialdo@mbuto default@ 3 hours ago, lasted 3 milliseconds
  │  add git remote origin
  │  args: jj git clone https://codeberg.org/arialdo/jj-playground1.git
  ○  23c04169eec1 arialdo@mbuto 3 hours ago, lasted 6 milliseconds
  │  add workspace 'default'
  ○  000000000000 root()

As expected, everything originates from 000000000000, the origin of times. From there you can travel through all the commands you ran. Each command created a snapshot of the whole repository.

It's a repository of your repository's history.

Rewind!

Restoring the repository exactly as it was before an operation is trivial. Each operation has its ID which you can reference with the command jj op restore.

You want to go back to when you performed:

jj git clone https://codeberg.org/arialdo/jj-playground1.git
cd jj-playground1
jj bookmark track '*' --remote origin

Solution

  • You run jj op log.
  • You identify the item for the command git remote remove origin. It should be the 5th operation, from 000000000000.
  • Find its ID. Then run: jj op restore <ID>

Spot on? Congrats, this was challenging!

You could also use:

$ jj op restore 000000000000+++++

to indicate the 5th op (+++++) after 000000000000.

Check the file system and the history log: everything is back to the moment you cloned the repo.

Like Emacs, Jujutsu Never Forgets

If you inspect the output of jj op log you will find that your last jj op restore has been appended to the top of all the other operation logs. So, you can still undo it by restoring its parent.

Basically:

  • Every operation, including op restore and undo, appends a full snapshot to the op log.
  • op restore reproduces an old snapshot and appends the result to the history.
  • undo restores the previous op.

We've all dreaded performing risky operations in Git. Armed with these tools, you should never feel that way again.

Ready?

After:

$ jj op restore 000000000000+++++

your repo should be:

  ○  zx       Click alternates Xs and Os main
  ○  v        Click sets a X
  ○  s        Square has state
  │ ○  o        Play instructions
  │ ○  kx       Play manual
  ├─╯
  ○  n        Square is interactive
  ○  ru       Board() invokes Square()
  ├─╮
  ○ │  ym       fix name: Square -> Board
  ○ │  x        WIP delete me
  ○ │  yz       LICENSE
  ○ │  ws       A board full of X
  ├─╯
  ○  kk       Displays X X
  ○  wx       Fails
  ○  rx       Scaffold applicatio
  ◆  zz   🔒  empty

Good. You are ready to play with rebase and squash.