diff --git a/src-tauri/src/git.rs b/src-tauri/src/git.rs index d67b573..4179308 100644 --- a/src-tauri/src/git.rs +++ b/src-tauri/src/git.rs @@ -1625,11 +1625,6 @@ pub async fn start_interactive_rebase( } let base_hash = verify_commit(&repo, &base)?; - ensure_ancestor( - &repo, - &base_hash, - "The selected base must be an ancestor of HEAD.", - )?; let available = interactive_rebase_commits_for_repo(&repo, &base_hash)?; validate_rebase_plan(&available, &plan)?; @@ -1765,11 +1760,6 @@ fn interactive_rebase_commits_for_repo( base: &str, ) -> Result, String> { let base_hash = verify_commit(repo, base)?; - ensure_ancestor( - repo, - &base_hash, - "The selected base must be an ancestor of HEAD.", - )?; let range = format!("{base_hash}..HEAD"); let merges = run_git(repo, ["rev-list", "--merges", range.as_str()])?; @@ -1809,20 +1799,6 @@ fn interactive_rebase_commits_for_repo( Ok(commits) } -fn ensure_ancestor(repo: &Path, commit: &str, message: &str) -> Result<(), String> { - let output = git_command() - .arg("-C") - .arg(repo) - .args(["merge-base", "--is-ancestor", commit, "HEAD"]) - .output() - .map_err(|err| format!("Could not start Git. Is Git installed? {err}"))?; - if output.status.success() { - Ok(()) - } else { - Err(message.to_string()) - } -} - fn validate_rebase_plan(commits: &[RebaseCommit], plan: &[RebasePlanItem]) -> Result<(), String> { if commits.is_empty() { return Err("There are no commits to rebase onto the selected base.".to_string()); @@ -5126,6 +5102,29 @@ mod tests { ); } + #[test] + fn interactive_rebase_accepts_a_diverged_base_branch() { + let repo = init_temp_repo("interactive_rebase_diverged"); + commit_initial_file(&repo.path); + let main_branch = git_output_test(&repo.path, ["branch", "--show-current"]); + run_git_test(&repo.path, ["checkout", "-q", "-b", "feature"]); + fs::write(repo.path.join("feature.txt"), "feature\n") + .expect("feature file should be written"); + run_git_test(&repo.path, ["add", "feature.txt"]); + run_git_test(&repo.path, ["commit", "-q", "-m", "feature commit"]); + run_git_test(&repo.path, ["checkout", "-q", main_branch.as_str()]); + fs::write(repo.path.join("main.txt"), "main\n").expect("main file should be written"); + run_git_test(&repo.path, ["add", "main.txt"]); + run_git_test(&repo.path, ["commit", "-q", "-m", "main advanced"]); + run_git_test(&repo.path, ["checkout", "-q", "feature"]); + + let commits = interactive_rebase_commits_for_repo(&repo.path, &main_branch) + .expect("diverged base should be accepted"); + + assert_eq!(commits.len(), 1); + assert_eq!(commits[0].summary, "feature commit"); + } + #[test] fn reflog_restore_creates_a_recovery_branch_without_resetting_existing_branch() { let repo = init_temp_repo("reflog_restore"); diff --git a/src/App.svelte b/src/App.svelte index bf6d18a..abac9f0 100644 --- a/src/App.svelte +++ b/src/App.svelte @@ -4221,7 +4221,7 @@ {#if reflogOpen} entry.selector === "HEAD@{0}")?.hash ?? ""} isLoading={reflogLoading} {isBusy} {operation}