GitoxideLabs/gitoxide · error

the current checkout has a pending rebase; time-travel to…

Error message

the current checkout has a pending rebase; time-travel to HEAD before editing it

What it means

`reject_pending_checkout_path` walks from a commit id up its first-parent chain and fails if any ancestor is a pending rebase commit. The currently checked-out history contains an unfinished (pending) rebase; editing it requires first time-traveling back to HEAD, otherwise the edit would operate on provisional rebase state.

Solutions

  1. Time-travel back to HEAD (abandon/complete the pending rebase checkout) before running the edit, as the message instructs.
  2. Complete the in-progress rebase (resolve conflicts and continue) then retry the edit.
  3. Abort the pending rebase, then re-run the edit operation.
  4. Pick a different target commit that is not on a pending rebase path.

Example fix

// before: editing while a pending rebase is checked out
edit.perform(repo, target_id)?; // bails
// after: return to HEAD first
time_travel_to_head(repo)?; // restore checkout to HEAD
edit.perform(repo, target_id)?;
Defensive patterns

Strategy: validation

Validate before calling

// walk first-parent chain from the edit target before editing
let mut id = target_id;
let mut seen = std::collections::HashSet::new();
while seen.insert(id) {
    let c = repo.find_commit(id)?.decode()?.into_owned()?;
    if gix_tix::edit::rebase::is_pending(&c) { time_travel_to_head(repo)?; break; }
    match c.parents.first().copied() { Some(p) => id = p, None => break }
}

Try / catch

match edit::perform(repo, target_id) {
    Err(e) if e.to_string().contains("pending rebase") => {
        time_travel_to_head(repo)?;
        edit::perform(repo, target_id)
    }
    other => other,
}

Prevention

When it happens

Trigger: Any edit operation that resolves a checkout path via `reject_pending_checkout_path` when walking `commit.parents.first()` reaches a commit for which `is_pending()` is true — i.e. the commit chain being edited includes a pending rebase commit reachable from the current checkout.

Common situations: User is in the middle of an interactive rebase (detached pending commits exist) and tries to run an edit/undo/rewrite command against an ancestor; automation scripts invoked while a rebase is paused mid-conflict.

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


AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08). Data as JSON: /api/errors/387a3d96e81a4df9. Report an issue: GitHub.

Appendix: source

Thrown at gix-tix/src/edit/rebase.rs:2571

            }
        }
    }
    if repeat
        && let Some(base) = affected.first()
        && let Some(parent) = graph.parents_of(*base).and_then(|parents| parents.first().copied())
        && is_pending(&repo.find_commit(parent)?.decode()?.into_owned()?)
    {
        anyhow::bail!("the parent of a repeated rebase must not be pending");
    }
    Ok(())
}

fn reject_pending_checkout_path(repo: &gix::Repository, mut id: ObjectId) -> Result<()> {
    let mut seen = HashSet::new();
    while seen.insert(id) {
        let commit = repo.find_commit(id)?.decode()?.into_owned()?;
        if is_pending(&commit) {
            anyhow::bail!("the current checkout has a pending rebase; time-travel to HEAD before editing it");
        }
        let Some(parent) = commit.parents.first().copied() else {
            break;
        };
        id = parent;
    }
    Ok(())
}

enum TreeRewrite {
    Complete(ObjectId),
    Conflict {
        ours: ObjectId,
        merged: ObjectId,
        conflicts: Vec<gix::merge::tree::Conflict>,
    },
}

View on GitHub (pinned to e73179060b)