2021-12-17 21:28:09 +00:00
|
|
|
# Operation log
|
|
|
|
|
|
|
|
|
|
|
|
## Introduction
|
|
|
|
|
|
|
|
Jujutsu records each operation that modifies the repo in the "operation log".
|
|
|
|
You can see the log with `jj op log`. Each operation object contains a snapshot
|
|
|
|
of how the repo looked at the end of the operation. We call this snapshot a
|
|
|
|
"view" object. The view contains information about where each branch, tag, and
|
|
|
|
Git ref (in Git-backed repos) pointed, as well as the set of heads in the repo,
|
2022-09-18 21:46:12 +00:00
|
|
|
and the current working-copy commit. The operation object also (in addition to
|
|
|
|
the view) contains pointers to the operation(s) immediately before it, as well
|
|
|
|
as metadata about the operation, such as timestamps, username, hostname,
|
|
|
|
description.
|
2021-12-17 21:28:09 +00:00
|
|
|
|
|
|
|
The operation log allows you to undo an operation (`jj op undo`), which doesn't
|
|
|
|
need to be the most recent one. It also lets you restore the entire repo to the
|
|
|
|
way it looked at an earlier point (`jj op restore`).
|
|
|
|
|
|
|
|
|
|
|
|
## Concurrent operations
|
|
|
|
|
|
|
|
One benefit of the operation log (and the reason for its creation) is that it
|
|
|
|
allows lock-free concurrency -- you can run concurrent `jj` commands without
|
|
|
|
corrupting the repo, even if you run the commands on different machines that
|
|
|
|
access the repo via a distributed file system (as long as the file system
|
|
|
|
guarantees that a write is only visible once previous writes are visible). When
|
|
|
|
you run a `jj` command, it will start by loading the repo at the latest
|
|
|
|
operation. It will not see any changes written by concurrent commands. If there
|
|
|
|
are conflicts, you will be informed of them by subsequent `jj st` and/or
|
|
|
|
`jj log` commands.
|
|
|
|
|
|
|
|
As an example, let's say you had started editing the description of a change and
|
|
|
|
then also update the contents of the change (maybe because you had forgotten the
|
|
|
|
editor). When you eventually close your editor, the command will succeed and
|
|
|
|
e.g. `jj log` will indicate that the change has diverged.
|
|
|
|
|
|
|
|
|
|
|
|
## Loading an old version of the repo
|
|
|
|
|
|
|
|
The top-level `--at-operation/--at-top` option allows you to load the repo at a
|
|
|
|
specific operation. This can be useful for understanding how your repo got into
|
|
|
|
the current state. It can be even more useful for understanding why someone
|
|
|
|
else's repo got into its current state.
|
|
|
|
|
|
|
|
When you use `--at-op`, the automatic snapshotting of the working copy will not
|
|
|
|
take place. When referring to a revision with the `@` symbol (as many commands
|
2022-09-18 21:46:12 +00:00
|
|
|
do by default), that will resolve to the working-copy commit recorded in the
|
2021-12-17 21:28:09 +00:00
|
|
|
operation's view (which is actually how it always works -- it's just the
|
|
|
|
snapshotting that's skipped with `--at-op`).
|
|
|
|
|
2022-09-18 21:46:12 +00:00
|
|
|
As a top-level option, `--at-op` can be passed to any command. However, you
|
2021-12-17 21:28:09 +00:00
|
|
|
will typically only want to run read-only commands. For example, `jj log`,
|
|
|
|
`jj st`, and `jj diff` all make sense. It's still possible to run e.g.
|
|
|
|
`jj --at-op=<some operation ID> describe`. That's equivalent to having started
|
|
|
|
`jj describe` back when the specified operation was the most recent operation
|
|
|
|
and then let it run until now (which can be done for that particular command by
|
|
|
|
not closing the editor). There's practically no good reason to do that other
|
|
|
|
than to simulate concurrent commands.
|