Skip to content

cli:converge: new jj converge command - #9802

Merged
drieber merged 3 commits into
mainfrom
push-nuzsrntnyktx
Aug 19, 2026
Merged

cli:converge: new jj converge command#9802
drieber merged 3 commits into
mainfrom
push-nuzsrntnyktx

Conversation

@drieber

@drieber drieber commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Checklist

If applicable:

  • I have updated CHANGELOG.md
  • I have updated the documentation (README.md, docs/, demos/)
  • I have updated the config schema (cli/src/config-schema.json)
  • I have added/updated tests to cover my changes
  • I fully understand the code that I am submitting (what it does,
    how it works, how it's organized), including any code drafted by an LLM.
  • For any prose generated by an LLM, I have proof-read and copy-edited with
    an eye towards deleting anything that is irrelevant, clarifying anything
    that is confusing, and adding details that are relevant. This includes,
    for example, commit descriptions, PR descriptions, and code comments.

Comment thread cli/src/commands/converge.rs Outdated
Comment thread cli/src/commands/converge.rs Outdated
Comment thread cli/src/commands/converge.rs Outdated
Comment thread cli/src/commands/converge.rs Outdated
Comment thread cli/src/commands/converge.rs Outdated
Comment thread CHANGELOG.md Outdated
Comment thread cli/src/commands/converge.rs Outdated
@drieber
drieber force-pushed the push-nuzsrntnyktx branch from 495c622 to 56c2d43 Compare July 13, 2026 16:00
Comment thread lib/src/converge.rs

@mirkomartn mirkomartn left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm definitely out of my depth here, so apologies for any dumb questions.

Comment thread lib/src/converge.rs Outdated
Comment thread lib/src/converge.rs
Comment thread cli/src/commands/converge.rs Outdated
Comment thread lib/src/converge.rs Outdated
Comment thread lib/tests/test_converge.rs
@drieber
drieber force-pushed the push-nuzsrntnyktx branch 3 times, most recently from 862d19e to f668d14 Compare July 17, 2026 17:46
Comment thread cli/src/commands/converge.rs Outdated
Comment thread cli/src/commands/converge.rs Outdated
@drieber
drieber force-pushed the push-nuzsrntnyktx branch 8 times, most recently from ab44dd2 to d2c3861 Compare July 20, 2026 22:44
@drieber

This comment was marked as outdated.

@drieber
drieber force-pushed the push-nuzsrntnyktx branch 3 times, most recently from 50d468b to 82cfff1 Compare July 21, 2026 00:50
@drieber

This comment was marked as outdated.

Comment thread cli/src/commands/converge.rs Outdated
Comment thread cli/src/commands/converge.rs Outdated
Comment thread cli/src/commands/converge.rs Outdated
Comment thread cli/src/commands/converge.rs
Comment thread cli/src/commands/converge.rs
Comment thread CHANGELOG.md Outdated
Comment thread CHANGELOG.md Outdated
@drieber
drieber force-pushed the push-nuzsrntnyktx branch 3 times, most recently from 5ce972b to 8b1bd9a Compare July 21, 2026 21:35
Comment thread cli/src/commands/converge.rs Outdated
Comment thread cli/src/commands/converge.rs Outdated
Comment thread cli/src/commands/converge.rs
@drieber
drieber force-pushed the push-nuzsrntnyktx branch from 8b1bd9a to 1cb24dd Compare July 21, 2026 22:23
@drieber
drieber force-pushed the push-nuzsrntnyktx branch from b8164f2 to 515bc1f Compare August 16, 2026 16:54
Comment thread lib/src/converge.rs
Comment thread lib/src/converge.rs Outdated
Comment thread lib/src/converge.rs Outdated
Comment thread cli/tests/test_converge_command.rs Outdated
Comment thread cli/tests/test_converge_command.rs
Comment thread cli/src/commands/converge.rs Outdated
Comment thread cli/src/commands/converge.rs Outdated
Comment thread cli/src/commands/converge.rs Outdated
Comment thread cli/src/commands/converge.rs Outdated
Comment thread cli/src/commands/converge.rs
Comment thread cli/src/commands/converge.rs Outdated
@drieber
drieber force-pushed the push-nuzsrntnyktx branch 8 times, most recently from dcd9bb3 to 3c17e88 Compare August 18, 2026 01:50
…r commit

Why this change?
----------------

When the heuristics used by converge_change cannot come up with a description,
author and/or parents for the solution, it produces ConvergedAttribute::unsolved.
The heuristics use dominator value algorithm to create a Merge<V> --a merge of
values, e.g. a Merge<String> for descriptions or Merge<Vec<CommitId>> for
parents. The heuristics fail when the Merge<V> does not resolve trivially.

ConvergedAttribute::unsolved includes the CommitId of the "base commit". The base
commit is "a" commit in the evolution history that "has" the dominator value. In
converge.rs we call this a "value producer". For example the description merge
may be:

```
    Merge(add: "bar", remove: "foo", add: "baz").
```

That merge does not resolve trivially. The "base commit" is a commit in the
truncated evolution graph that has description "foo". It is guaranteed that
such a commit exists, but there could be more than one. The changes here affect
how that choice is made. converge_change MUST choose deterministically, and
should try to make a decent choice.

Where is ConvergeAttribute::unsolved.base_commit used? A follow up change in this
sequence introduces the `jj converge` command. That command uses the base_commit
when asking the user to merge divergent commit descriptions: it presents the user
with an editor with the conflicting descriptions with conflict markers and
conflict labels. The conflict label marker for the base description is the
conflict labels of the base commit.

There is another place where the "base commit" is used: in conflict markers in
the MergedTree of the solution commit.

What is the change?
-------------------

Previously commit timestamp was not considered at all when choosing a base commit
among two or more value producers. Now commit timestamp is considered. A commit
with a more recent timestamp is given preference over a commit with an older
timestamp. Why not simply use change offset ordering? The algorithm DOES use
change ordering when choosing the base commit, but on some backends not all
commits for a given change-id have change offsets. For example at Google
change offset is calculated only for some commits (I forget the details, I
think it is only for visible commits or something like that).
@drieber
drieber force-pushed the push-nuzsrntnyktx branch 2 times, most recently from f360811 to 044f710 Compare August 18, 2026 03:27
The motivation is to make the return type more appropriate for use in the converge
command. Before this commit:

```
CommitsByChangeId = HashMap<ChangeId, HashMap<CommitId, Commit>>
```

After this commit:

```
CommitsByChangeId = BTreeMap<ChangeId, Vec<Commit>>
```

The change-ids are now sorted. Also, the commits for a given (divergent) change-id
are now sorted by revset-engine order.
@drieber
drieber force-pushed the push-nuzsrntnyktx branch 2 times, most recently from 42e1bc3 to c0779d9 Compare August 18, 2026 03:56
Comment thread cli/src/commands/converge.rs Outdated
Comment thread cli/src/commands/converge.rs Outdated
Comment thread cli/src/commands/converge.rs Outdated
Comment thread cli/src/commands/converge.rs Outdated
Comment thread cli/src/commands/converge.rs Outdated
Comment thread cli/src/commands/converge.rs Outdated
Comment thread cli/src/commands/converge.rs Outdated
Comment thread cli/src/commands/converge.rs Outdated
Comment thread cli/src/commands/converge.rs
Comment thread CHANGELOG.md Outdated
@drieber
drieber force-pushed the push-nuzsrntnyktx branch 4 times, most recently from 5776cf7 to 9251ab0 Compare August 19, 2026 00:22
`jj converge` allows users to "fix" divergence. The command tries to
create a new commit for the divergent change that rewrites all divergent
commits. The command tries to do this automatically, but falls back to
prompting the user for pieces of information as needed.

The command uses the lib/converge.rs library to do most of the work.

The command takes an optional --search_space revset (it looks for
divergent commits matching that revset). If not specified the command
uses a new `revsets.converge` system revset (mutable() & divergent()).

If the command cannot automatically merge the descriptions, the user's
text editor is invoked to let the user merge the divergent descriptions
manually (as if they were conflicts on a "description" file).

The command has a --interactive=true/false flag to allow users to invoke
it without prompting the user.
@drieber
drieber force-pushed the push-nuzsrntnyktx branch from 9251ab0 to 59ac566 Compare August 19, 2026 00:40

@martinvonz martinvonz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! This looks good to me. I'm sure we'll discover things to polish, but that can be done later. Hearing from users will be valuable.

@drieber
drieber added this pull request to the merge queue Aug 19, 2026
Merged via the queue into main with commit 9dd95ff Aug 19, 2026
37 checks passed
@drieber
drieber deleted the push-nuzsrntnyktx branch August 19, 2026 03:04
@drieber

drieber commented Aug 19, 2026

Copy link
Copy Markdown
Contributor Author

Thanks! This looks good to me. I'm sure we'll discover things to polish, but that can be done later. Hearing from users will be valuable.

Thank you for the review! I know this was a large PR, I appreciate all the feedback I got. I already have some ideas of what could be improved here, and most importantly I hope to get user feedback. For now I have #10009 to mention jj converge in docs/guides/divergence.md

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants