gitbutlerapp/gitbutler · error
Cannot currently rebase a commit so that it becomes the…
Error message
Cannot currently rebase a commit so that it becomes the first commit in the history
What it means
During `rebase` execution, a `Pick` step is reached when `cursor` is `None` (no parent position established yet) and the picked commit has at least one parent. The only supported root case is a parentless commit, which is created as a new root; rebasing a non-root commit into the very first commit of history would require dropping its parents, which is intentionally not implemented (see the TODO in the source).
Solutions
- Reorder the steps so a parentless (root) commit comes first, or supply a valid `base` so the cursor is initialized.
- If the goal is to make a commit root, flatten it by squashing it into the following commit instead of picking it first.
- Create the desired history as new commits rather than rebasing an existing parented commit into position zero.
Example fix
// before steps = [pick(commit_with_parent), pick(root_commit)]; // base=None -> error // after steps = [pick(root_commit), pick(commit_with_parent)];
Defensive patterns
Strategy: validation
Validate before calling
fn can_pick_at_front(repo: &gix::Repository, commit_id: gix::ObjectId, base: Option<gix::ObjectId>) -> anyhow::Result<bool> {
Ok(base.is_none() && repo.find_commit(commit_id)?.parent_ids().next().is_none())
} Type guard
fn is_root_commit(repo: &gix::Repository, id: gix::ObjectId) -> anyhow::Result<bool> {
Ok(repo.find_commit(id)?.parent_ids().next().is_none())
} Try / catch
match rebase(repo, base, base_substitute, steps, pick_mode) {
Err(e) if e.to_string().contains("first commit in the history") => {
// reorder steps so a root commit comes first, or set a base
}
other => other,
} Prevention
- When base is None, ensure the first Pick step targets a parentless (root) commit.
- Never plan an ordinary parented commit as the new first commit; use a base or reorder instead.
- Validate the step sequence before running the rebase.
When it happens
Trigger: Running a rebase where `base` is `None` (no base commit) and a `RebaseStep::Pick` targets a commit with one or more parents, so `cursor` is `None` at that point in the step loop (crates/but-rebase/src/lib.rs:303).
Common situations: Trying to move an ordinary mid-history commit to the front of a stack; constructing an initial-history rewrite from commits that were created with parents; scripted rebases that assume root creation works for any commit.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Can't squash if previous commit is missing
- A matching parent can't be found in the output graph
- A parent in the output graph is not a pick
- An edge with desired order
- Attempted to update the symbolic reference
AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18).
Data as JSON: /api/errors/547470c815acb3ea.
Report an issue: GitHub.
Appendix: source
Thrown at crates/but-rebase/src/lib.rs:305
let mut new_commit = commit;
if let Some(new_message) = new_message {
new_commit.message =
but_core::commit::rewrite_conflict_markers_on_message_change(
new_commit.message.as_ref(),
new_message,
);
}
cursor = Some(commit::create(
repo,
new_commit,
DateMode::CommitterUpdateAuthorKeep,
SignCommit::IfSignCommitsEnabled,
None,
)?);
}
None => {
// TODO: should this be supported? This would be as easy as forgetting its parents.
bail!(
"Cannot currently rebase a commit so that it becomes the first commit in the history"
)
}
}
}
}
RebaseStep::SquashIntoPreceding {
commit_id,
new_message,
} => {
let Some(cursor) = &mut cursor else {
bail!("Can't squash if previous commit is missing");
};
last_seen_commit = Some(commit_id);
let base_commit = repo.find_commit(*cursor)?;
let new_commit = cherry_pick_one(
repo,
*cursor,View on GitHub (pinned to 58e5313667)