In short: jj loads the workspace without snapshotting and resolves X. It calls
update_op_heads(parents of X → X), so X becomes a head next to the current one. Then
resolve_op_heads runs: if X turns out to be an ancestor of another head, it is simply
dropped again and nothing happens. Otherwise the heads are merged into a new operation,
reconcile divergent operations, and jj prints
The specified operation has been integrated with other existing operations.
The command is cmd_op_integrate. Its help explains when
that's needed: operations are integrated automatically, but --no-integrate-operation or an
internal error can leave one out (source). jj points you here itself
when the working copy's operation turns out to be a sibling of the loaded one. Op heads and the merge of
concurrent operations are described on the operations
page.
1. Command-line surface
| Argument | Type | Default | Meaning |
|---|---|---|---|
OPERATION (positional) | operation expression | required | The operation to integrate (source). |
2. Configuration
None. The workspace is loaded with workspace_helper_no_snapshot, so no snapshot of the
working copy is taken first (source,
helper). The global --no-integrate-operation is the
flag that creates operations needing this command.
3. End-to-end flow
4. Core architecture touchpoints
| Structure | Read / write | How | Explained on |
|---|---|---|---|
| Op heads store | updated | X added, its parents removed; then the merged operation replaces the heads it merged (update_op_heads, source). | operations |
| Operation and view stores | written | The merge writes a new view and operation whose parents are the merged heads. | operations |
| Commits | maybe rewritten | If one side rewrote commits that the other built on, the merge rebases them and prints Rebased N descendant commits onto commits rewritten by other operation. (source). | operations |
| Working copy | not touched | No snapshot and no checkout. The next command reloads it against the new head. | working-copy |
5. Transaction and operation
- No transaction of the command's own. The only operation written is the merge, created inside
resolve_op_headsbyRepoLoader::merge_operations(source). - Operation description:
reconcile divergent operations, recorded with this workspace's name and the command's arguments (source). - Already integrated: nothing is written and nothing printed (test).
- Undoing it:
jj undorefuses a merge operation;jj op restoreto one of the merged operations works.
6. Algorithm and invariants
-
update_op_heads(old, new)removes the old heads and adds the new one. Passing X's parents as "old" means that if a parent was a head, X replaces it, and otherwise X is simply added next to the existing heads (source). -
resolve_op_headsreads the heads. With several, it locks, re-reads, and drops heads that are ancestors of other heads. One left: it's used as is, and the dropped ones are removed from the op heads. Still several: they're sorted by end time and handed to the resolver. -
The resolver calls
merge_operations, which merges the repos at those operations, using their closest common ancestors as bases, and writes the result as one operation. The op heads are then replaced by it.
Invariants: nothing is removed from the operation store. Integrating twice is harmless. After the command there is exactly one op head, unless another process raced it.
7. Errors and edge cases
| Message | When | Source |
|---|---|---|
The specified operation has been integrated with other existing operations. | A merge operation was created. | integrate.rs |
| (no output) | X is already in the operation log. | test |
Internal error: The repo was loaded at operation <a>, which seems to be a sibling of the working copy's operation <b>, hint Run `jj op integrate <b>` … | Printed by other commands; the reason to run this one. | command_error.rs |
Rebased <n> descendant commits onto commits rewritten by other operation. | The merge had to rebase commits. | cli_util.rs |
| Operation-resolution errors | X doesn't resolve to one operation. | cli_util.rs |
8. Worked example
From upstream's test_integrate_sibling_operation. The test runs
jj new -m=first, then removes that operation from the op heads by hand, and runs
jj new -m=second --ignore-working-copy, which builds on the older operation. The working
copy still records the first one, so jj op log fails with the sibling error and its hint.
Running jj op integrate 4bffc36765bd fixes it:
Upstream's output and the new top of the operation log (source):
The specified operation has been integrated with other existing operations.
@ f28c8b5750f5 … default@ …
├─╮ reconcile divergent operations
│ │ args: jj op integrate 4bffc36765bd…