GitoxideLabs/gitoxide · error
a tree change cannot be amended from the worktree
Error message
a tree change cannot be amended from the worktree
What it means
During an amend, `amend_path_tree` can apply a single path change taken from the index or the worktree, but a `ChangeGroup::Tree` change is a whole-tree (submodule/tree-entry) change that cannot be reproduced by rebuilding trees from worktree state. The library intentionally refuses rather than silently producing a wrong tree. Callers must re-run the operation without amending, or handle tree changes separately.
Solutions
- Amend only file (blob) changes; leave tree changes such as submodule pointer updates to a new commit or to `git submodule update`.
- Update the submodule to a recorded state so the change stops appearing as a tree change, then retry the amend.
- If support for amending tree changes is desired, implement it via tree editors (apply_path_from_tree) instead of the worktree path.
Example fix
// before: selecting a submodule change and amending tix amend # ChangeGroup::Tree -> bail // after: stage only file changes, or commit the submodule bump separately let changes: Vec<_> = changes.into_iter().filter(|c| c.group != ChangeGroup::Tree).collect();
Defensive patterns
Strategy: validation
Validate before calling
// Rust: check the change group before amending
if change.group == crate::ChangeGroup::Tree {
eprintln!("skip amend: tree change {:?}", change.path);
} else {
amend(repo, change)?;
} Type guard
fn is_amendable(change: &PathChange) -> bool {
matches!(change.group, crate::ChangeGroup::Staged | crate::ChangeGroup::Unstaged)
} Prevention
- Filter the change list to blob/file changes before invoking amend.
- Handle submodule pointer updates through `git submodule` workflows, not worktree amends.
When it happens
Trigger: Calling the tix amend path so that `perform_inner` dispatches `amend_path_tree` with a `PathChange` whose `group` is `crate::ChangeGroup::Tree` — i.e. the selected change is a tree (e.g. submodule pointer) change rather than a staged or unstaged file change.
Common situations: Amending a commit that changed a submodule pointer or other gitlink/tree entry; selecting a tree-type entry in the interactive change list and asking tix to fold it into the head 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
- Need a worktree to clean, this is a bare repository
- JSON output isn't implemented yet
- cannot amend with unresolved index conflicts
- review commits can amend only staged paths
- cannot spill an unmerged path
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/dd632354ffc35575.
Report an issue: GitHub.
Appendix: source
Thrown at gix-tix/src/edit/head.rs:217
index: &gix::index::File,
) -> Result<ObjectId> {
match change.group {
crate::ChangeGroup::Staged => {
let index_tree = create::index_tree(repo, index)?;
apply_path_from_tree(repo, commit_tree, index_tree, change)
}
crate::ChangeGroup::Unstaged => {
let baseline = repo.find_tree(commit_tree)?;
create::worktree_tree_with_changes(
repo,
&baseline,
&crate::Changes {
paths: vec![change.clone()],
..crate::Changes::default()
},
)
}
crate::ChangeGroup::Tree => anyhow::bail!("a tree change cannot be amended from the worktree"),
}
}
fn apply_path_from_tree(
repo: &gix::Repository,
commit_tree: ObjectId,
source_tree: ObjectId,
change: &PathChange,
) -> Result<ObjectId> {
let mut editor = repo.find_tree(commit_tree)?.edit()?;
if change.kind == ChangeKind::Renamed
&& let Some(source) = &change.source
{
editor.remove(source)?;
}
if change.kind == ChangeKind::Deleted {
editor.remove(&change.path)?;
} else {View on GitHub (pinned to e73179060b)