GitoxideLabs/gitoxide · error
an unborn history is required to create a root commit
Error message
an unborn history is required to create a root commit
What it means
Commit creation in tix requires an unborn HEAD when no parent commit was supplied, i.e. creating a root commit is only valid when the repository has no commits yet. If a parent is not given but HEAD points at an existing commit, the operation would silently orphan history, so it bails with this message. Supplying an explicit parent is the supported way to create non-root commits.
Solutions
- Pass the intended parent commit explicitly (e.g. the current HEAD commit) instead of relying on root-commit mode.
- Use the amend workflow if the goal is to modify the existing HEAD commit.
- Only create root commits in a repository with unborn HEAD (no commits yet).
Example fix
// before: parent=None on a repo with existing history -> bail let prepared = create::prepare(&repo, None, ...)?; // after let head_id = repo.head_id()?.detach(); let prepared = create::prepare(&repo, Some(head_id), ...)?;
Defensive patterns
Strategy: validation
Validate before calling
let head = repo.head()?;
let is_unborn = head.is_unborn();
if parent.is_none() && !is_unborn {
anyhow::bail!("supply an explicit parent (or use amend) on a repo with history");
} Try / catch
match result {
Err(e) if e.to_string().contains("unborn history is required") => {
// retry with current HEAD as parent
}
other => other?,
} Prevention
- Always pass the intended parent commit unless you deliberately mean root-commit creation.
- Check `repo.head().is_unborn()` before choosing root-commit mode.
- Use the amend workflow to modify existing history rather than re-creating commits.
When it happens
Trigger: Calling `Prepared::prepare`/`prepare_empty`/`prepare_from` (via `prepare_inner`) with `parent == None` while HEAD resolves to an existing commit instead of being unborn.
Common situations: Running a create/edit command in a repository that already has history without specifying the intended parent; confusing 'new commit' with 'amend'; scripting that drops the parent argument on non-empty repos.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- the new commit would be empty; use --allow-empty to create…
- the new commit would be empty; use new-empty instead
- Tried to use as tree, but was
- Tried to use as commit, but was
- Tried to use as tag, but was
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/c164953edfff4887.
Report an issue: GitHub.
Appendix: source
Thrown at gix-tix/src/edit/create.rs:61
author: Option<&gix::bstr::BStr>,
todo: bool,
) -> Result<Prepared> {
prepare_inner(repo, parent, false, source, author, todo)
}
fn prepare_inner(
mut repo: gix::Repository,
parent: Option<ObjectId>,
empty: bool,
source: Source,
author_override: Option<&gix::bstr::BStr>,
todo: bool,
) -> Result<Prepared> {
repo.workdir().context("creating a commit requires a worktree")?;
let head = repo.head().context("could not read HEAD before creating a commit")?;
let head_id = head.id().map(gix::Id::detach);
if parent.is_none() && !head.is_unborn() {
anyhow::bail!("an unborn history is required to create a root commit");
}
if let Some(parent) = parent {
repo.find_commit(parent)
.context("could not find the selected parent commit")?;
}
if parent.is_none() {
head.referent_name().context("an unborn HEAD must point to a branch")?;
}
let editor = repo
.editor_command()
.context("could not prepare Git editor")?
.context("no Git editor is available")?;
let mut author = repo
.author()
.context("no Git author is configured")?
.context("could not resolve the Git author")?
.to_owned()
.context("could not own the Git author")?;View on GitHub (pinned to e73179060b)