GitoxideLabs/gitoxide · error
review commits cannot be copied
Error message
review commits cannot be copied
What it means
The copy operation refuses to copy commits that carry a review reference (a commit marked as a review point via `super::review::reference`). Review commits have special meaning in tix's review tracking; copying one would create a duplicate or break the review bookkeeping, so the plan builder bails out before any rewrite.
Solutions
- Copy a different commit that does not carry a review reference.
- Remove or complete the review reference on the source commit first, then retry the copy.
- If the intent is to reuse review work, use the review-specific workflow instead of a raw copy.
Example fix
// before
tix copy <review-commit-id> <target>
// after
if super::review::reference(&source_commit)?.is_some() {
eprintln!("source carries a review reference; pick another commit");
return Ok(());
}
tix copy(source, target) Defensive patterns
Strategy: validation
Validate before calling
let commit = repo.find_commit(source)?.decode()?.into_owned()?;
if super::review::reference(&commit)?.is_some() {
eprintln!("source is a review commit and cannot be copied");
return Ok(());
} Type guard
fn is_review_commit(repo: &gix::Repository, id: ObjectId) -> anyhow::Result<bool> {
let c = repo.find_commit(id)?.decode()?.into_owned()?;
Ok(super::review::reference(&c)?.is_some())
} Try / catch
match copy_insert_plan(&repo, &graph, source, target) {
Err(e) if e.to_string().contains("review commits") => eprintln!("pick a non-review commit as source"),
other => other?,
} Prevention
- Hide or annotate review commits in commit pickers
- Centralize review-reference detection in a helper used before any history-rewriting operation
- Complete or clear review references before bulk copy operations
When it happens
Trigger: Calling `copy_insert_plan(repo, graph, source, target)` where the decoded source commit has an associated review reference (i.e. `super::review::reference(&source_commit)?` returns `Some`).
Common situations: Copying a commit that is the tip of a review branch or holds review metadata; batch scripts that copy many commits and hit the one carrying the review marker.
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
- copying a commit requires it to have exactly one parent
- copying a commit cannot rewrite root or merge commits
- moving a stack cannot rewrite root or merge commits
- has a pending rebase
- a checked-out review root cannot suspend while returning…
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/798b510d08228d6d.
Report an issue: GitHub.
Appendix: source
Thrown at gix-tix/src/edit/rebase.rs:562
graph: &HistoryGraph,
source: ObjectId,
target: ObjectId,
) -> Result<Plan> {
let source_parents = graph
.parents_of(source)
.context("the copy source is not in the loaded history")?;
let [_source_parent] = source_parents.as_slice() else {
anyhow::bail!("copying a commit requires it to have exactly one parent");
};
let source_commit = repo
.find_commit(source)
.context("could not find the copy source")?
.decode()
.context("could not decode the copy source")?
.into_owned()
.context("could not own the copy source")?;
if super::review::reference(&source_commit)?.is_some() {
anyhow::bail!("review commits cannot be copied");
}
if source == target {
anyhow::bail!("the copy source and target must differ");
}
let mut scope = graph
.descendants_in_parent_order(target)
.context("the copy target is not in the loaded history")?;
scope.retain(|id| *id != target);
let mut steps = vec![PlanStep {
parent: PlanParent::Existing(target),
commit: PlanCommit::Copy(source),
squash: Vec::new(),
}];
let mut step_by_id = HashMap::with_capacity(scope.len());
for id in &scope {
let parents = graph.parents_of(*id).context("an affected copy commit is incomplete")?;
let [parent] = parents.as_slice() else {View on GitHub (pinned to e73179060b)