Skip to content

Commit 9dd95ff

Browse files
committed
cli:converge: new jj converge command
`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.
1 parent 7e7ca71 commit 9dd95ff

9 files changed

Lines changed: 2342 additions & 2 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
2424
jj workspace can have its own Git HEAD. Existing repositories are migrated
2525
automatically.
2626

27+
* The new `jj converge` command attempts to automatically resolve divergence by
28+
creating a new commit that replaces the divergent commits. It applies
29+
heuristics to try to automatically come up with a good solution, and falls
30+
back to prompting the user if the heuristics are inconclusive. It can also run
31+
in non-interactive mode, which aborts if prompting would be needed.
32+
2733
### Fixed bugs
2834

2935
* The default pager flags now include `-K` (`--quit-on-intr`), so pressing

cli/src/command_error.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use jj_lib::config::ConfigFileSaveError;
2828
use jj_lib::config::ConfigGetError;
2929
use jj_lib::config::ConfigLoadError;
3030
use jj_lib::config::ConfigMigrateError;
31+
use jj_lib::converge::ConvergeError;
3132
use jj_lib::dsl_util::Diagnostics;
3233
use jj_lib::evolution::WalkPredecessorsError;
3334
use jj_lib::fileset::FilePatternParseError;
@@ -427,6 +428,19 @@ impl From<WalkPredecessorsError> for CommandError {
427428
}
428429
}
429430

431+
impl From<ConvergeError> for CommandError {
432+
fn from(err: ConvergeError) -> Self {
433+
match err {
434+
ConvergeError::Backend(err) => err.into(),
435+
ConvergeError::Index(err) => err.into(),
436+
ConvergeError::RevsetEvaluation(err) => err.into(),
437+
ConvergeError::WalkPredecessors(err) => err.into(),
438+
ConvergeError::IO(err) => err.into(),
439+
ConvergeError::Other(err) => internal_error(err),
440+
}
441+
}
442+
}
443+
430444
impl From<DiffEditError> for CommandError {
431445
fn from(err: DiffEditError) -> Self {
432446
user_error_with_message("Failed to edit diff", err)
@@ -507,6 +521,12 @@ impl From<TempTextEditError> for CommandError {
507521
}
508522
}
509523

524+
impl From<TempTextEditError> for ConvergeError {
525+
fn from(err: TempTextEditError) -> Self {
526+
Self::Other(Box::new(err))
527+
}
528+
}
529+
510530
impl From<TrailerParseError> for CommandError {
511531
fn from(err: TrailerParseError) -> Self {
512532
user_error(err)
@@ -936,7 +956,9 @@ fn revset_resolution_error_hints(err: &RevsetResolutionError) -> Vec<String> {
936956
kind: _,
937957
symbol: _,
938958
targets,
939-
} => vec![multiple_targets_hint(targets)],
959+
} => {
960+
vec![multiple_targets_hint(targets)]
961+
}
940962
RevsetResolutionError::EmptyString
941963
| RevsetResolutionError::WorkspaceMissingWorkingCopy { .. }
942964
| RevsetResolutionError::AmbiguousCommitIdPrefix(_)

0 commit comments

Comments
 (0)