{"record":{"id":"547470c815acb3ea","repo":"gitbutlerapp/gitbutler","slug":"cannot-currently-rebase-a-commit-so-that-it-becomes-the","errorCode":null,"errorMessage":"Cannot currently rebase a commit so that it becomes the first commit in the history","messagePattern":"Cannot currently rebase a commit so that it becomes the first commit in the history","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-rebase/src/lib.rs","lineNumber":305,"sourceCode":"                            let mut new_commit = commit;\n                            if let Some(new_message) = new_message {\n                                new_commit.message =\n                                    but_core::commit::rewrite_conflict_markers_on_message_change(\n                                        new_commit.message.as_ref(),\n                                        new_message,\n                                    );\n                            }\n                            cursor = Some(commit::create(\n                                repo,\n                                new_commit,\n                                DateMode::CommitterUpdateAuthorKeep,\n                                SignCommit::IfSignCommitsEnabled,\n                                None,\n                            )?);\n                        }\n                        None => {\n                            // TODO: should this be supported? This would be as easy as forgetting its parents.\n                            bail!(\n                                \"Cannot currently rebase a commit so that it becomes the first commit in the history\"\n                            )\n                        }\n                    }\n                }\n            }\n            RebaseStep::SquashIntoPreceding {\n                commit_id,\n                new_message,\n            } => {\n                let Some(cursor) = &mut cursor else {\n                    bail!(\"Can't squash if previous commit is missing\");\n                };\n                last_seen_commit = Some(commit_id);\n                let base_commit = repo.find_commit(*cursor)?;\n                let new_commit = cherry_pick_one(\n                    repo,\n                    *cursor,","sourceCodeStart":287,"sourceCodeEnd":323,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/but-rebase/src/lib.rs#L287-L323","documentation":"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).","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before\nsteps = [pick(commit_with_parent), pick(root_commit)]; // base=None -> error\n// after\nsteps = [pick(root_commit), pick(commit_with_parent)];","handlingStrategy":"validation","validationCode":"fn can_pick_at_front(repo: &gix::Repository, commit_id: gix::ObjectId, base: Option<gix::ObjectId>) -> anyhow::Result<bool> {\n    Ok(base.is_none() && repo.find_commit(commit_id)?.parent_ids().next().is_none())\n}","typeGuard":"fn is_root_commit(repo: &gix::Repository, id: gix::ObjectId) -> anyhow::Result<bool> {\n    Ok(repo.find_commit(id)?.parent_ids().next().is_none())\n}","tryCatchPattern":"match rebase(repo, base, base_substitute, steps, pick_mode) {\n    Err(e) if e.to_string().contains(\"first commit in the history\") => {\n        // reorder steps so a root commit comes first, or set a base\n    }\n    other => other,\n}","preventionTips":["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."],"tags":["rebase","git-history","unsupported-operation"],"backgroundTag":"unsupported-operation","analyzedSha":"58e5313667b857ef39a730e380af31816a7b1768","analyzedAt":"2026-09-18T06:50:32.052Z","contentChangedAt":"2026-09-18T06:50:32.052Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}