diff --git a/cli/src/commands/rebase.rs b/cli/src/commands/rebase.rs index 0e9534e1e9..38fc46f5f6 100644 --- a/cli/src/commands/rebase.rs +++ b/cli/src/commands/rebase.rs @@ -290,13 +290,27 @@ fn rebase_descendants( rebase_options: RebaseOptions, ) -> Result<(), CommandError> { workspace_command.check_rewritable(old_commits)?; + let (skipped_commits, old_commits) = old_commits + .iter() + .partition::, _>(|commit| commit.parents().eq(new_parents)); + for commit in skipped_commits.iter() { + writeln!( + ui.stderr(), + "Skipping rebase of commit {}", + short_commit_hash(commit.id()), + )?; + continue; + } + if old_commits.is_empty() { + return Ok(()); + } for old_commit in old_commits.iter() { check_rebase_destinations(workspace_command.repo(), new_parents, old_commit)?; } let mut tx = workspace_command.start_transaction(); // `rebase_descendants` takes care of sorting in reverse topological order, so // no need to do it here. - for old_commit in old_commits { + for old_commit in old_commits.iter() { rebase_commit_with_options( settings, tx.mut_repo(), @@ -330,6 +344,14 @@ fn rebase_revision( ) -> Result<(), CommandError> { let old_commit = workspace_command.resolve_single_rev(rev_str)?; workspace_command.check_rewritable([&old_commit])?; + if old_commit.parents().eq(new_parents) { + writeln!( + ui.stderr(), + "Skipping rebase of commit {}", + short_commit_hash(old_commit.id()), + )?; + return Ok(()); + } if new_parents.contains(&old_commit) { return Err(user_error(format!( "Cannot rebase {} onto itself", diff --git a/cli/tests/test_duplicate_command.rs b/cli/tests/test_duplicate_command.rs index c267cc925a..c021c1a9f7 100644 --- a/cli/tests/test_duplicate_command.rs +++ b/cli/tests/test_duplicate_command.rs @@ -323,9 +323,7 @@ fn test_rebase_duplicates() { let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["rebase", "-s", "a", "-d", "a-"]); insta::assert_snapshot!(stdout, @""); insta::assert_snapshot!(stderr, @r###" - Rebased 4 commits - Working copy now at: zsuskuln 29bd36b6 b | b - Parent commit : rlvkpnrz 2f6dc5a1 a | a + Skipping rebase of commit 2443ea76b0b1 "###); // Some of the duplicate commits' timestamps were changed a little to make them // have distinct commit ids. diff --git a/cli/tests/test_rebase_command.rs b/cli/tests/test_rebase_command.rs index ff0389faa7..97249d0351 100644 --- a/cli/tests/test_rebase_command.rs +++ b/cli/tests/test_rebase_command.rs @@ -145,7 +145,8 @@ fn test_rebase_branch() { let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["rebase", "-b=e", "-b=d", "-d=b"]); insta::assert_snapshot!(stdout, @""); insta::assert_snapshot!(stderr, @r###" - Rebased 2 commits + Skipping rebase of commit 514fa6b265d4 + Rebased 1 commits Working copy now at: znkkpsqq 9ca2a154 e | e Parent commit : zsuskuln 1394f625 b | b Added 1 files, modified 0 files, removed 0 files @@ -692,9 +693,7 @@ fn test_rebase_with_child_and_descendant_bug_2600() { test_env.jj_cmd_ok(&repo_path, &["rebase", "-s", "base", "-d", "root()"]); insta::assert_snapshot!(stdout, @""); insta::assert_snapshot!(stderr, @r###" - Rebased 4 commits - Working copy now at: vruxwmqv 13b23fa1 c | c - Parent commit : royxmykx 15092f8a b | b + Skipping rebase of commit 0c61db1be8c8 "###); // This should be a no-op insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"