feat(git): improve interactive rebase base handling and reflog display
The git module now correctly handles scenarios where the selected base branch is diverged from HEAD. This removes unnecessary ancestor checks during rebase planning, improving overall robustness of the feature. Additionally, the ReflogDialog component was updated to reliably retrieve the current HEAD hash for accurate display in the UI. - Removed strict ancestor checking when starting interactive rebase operations. - Updated App.svelte to accurately find and use the current HEAD entry from reflog data.
This commit is contained in:
+23
-24
@@ -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<Vec<RebaseCommit>, 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");
|
||||
|
||||
Reference in New Issue
Block a user