GitoxideLabs/gitoxide · error
the revisions have multiple editable fork points
Error message
the revisions have multiple editable fork points: {} What it means
The counterpart to the zero-candidate case: when `hidden_rebase_candidates()` returns more than one possible fork point, `rebase::prepare` refuses to guess, sorts the candidates by object id for deterministic reporting, and bails listing all of them. The user must narrow the base so exactly one candidate remains.
Solutions
- Pass a single, specific `-x/--hide` revision naming the exact intended fork point.
- Reduce the number of `-x` revisions to the one that is the true base.
- Inspect the candidate ids listed in the message with `gix log` to pick the right one.
- Rewrite/linearize the criss-cross history first if appropriate.
Example fix
// before gix tix rebase todo -x branch-a -x branch-b # two fork points // after gix tix rebase todo -x branch-a # one explicit fork point
Defensive patterns
Strategy: try-catch
Validate before calling
// Resolve candidate merge bases of the hidden and visible tips first; proceed only when exactly one exists.
Try / catch
match prepare(repo, &args) { Err(e) if e.to_string().contains("multiple editable fork points") => { let base = parse_first_candidate(&e.to_string()); let mut args2 = args.clone(); args2.hide = vec![base]; prepare(repo, &args2) } other => other } Prevention
- Pass exactly one explicit -x fork-point revision for ambiguous topologies.
- Detect criss-cross merge histories and specify the base manually.
- Parse the candidate list from the error message to disambiguate interactively.
When it happens
Trigger: Rebase prepare where the hidden and visible revisions share several merge-base-like candidates — typically when multiple `-x/--hide` revisions are given and they fork at different points, or criss-cross merge history yields multiple equally valid bases.
Common situations: Criss-cross merge topologies from repeated merges between two branches; passing several `-x` revisions from divergent remotes; rebasing a stacked branch whose base history was rewritten inconsistently.
Related errors
- the hidden and visible revisions have no editable fork point
- change ID prefix is ambiguous in the default Tix view
- rebase todo requires at least one -x/--hide revision when…
- show requires at least one -x/--hide revision when no…
- path does not name a file
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/6fffe5e54fa0ceb4.
Report an issue: GitHub.
Appendix: source
Thrown at gix-tix/src/command/rebase.rs:146
match event {
Event::Decorations(value) => decorations = value,
Event::Commits(commits) => app.extend_commits(commits),
Event::HiddenCommits(commits) => app.extend_hidden_commits(commits),
Event::Complete(value) => graph = Some(value),
Event::VisibleComplete | Event::Cancelled => {}
}
true
},
)?;
let graph = graph.context("history traversal did not produce a graph")?;
crate::update_hidden_branch_updates(&mut app, Some(&graph), &refs);
let mut candidates = app.hidden_rebase_candidates();
if candidates.len() != 1 {
if candidates.is_empty() {
anyhow::bail!("the hidden and visible revisions have no editable fork point");
}
candidates.sort_by_key(|(id, _)| *id);
anyhow::bail!(
"the revisions have multiple editable fork points: {}",
candidates
.iter()
.map(|(id, _)| id.to_string())
.collect::<Vec<_>>()
.join(", ")
);
}
let (base, scope) = candidates.pop().context("one rebase candidate was expected")?;
let (onto, onto_kind) = if args.update_base {
let onto = app
.hidden_branch_update(base)
.context("--update-base found no newer hidden local branch tip for the derived base")?;
(onto, todo::OntoKind::UpdatedBase)
} else {
(
args.onto
.as_deref()View on GitHub (pinned to e73179060b)