GitoxideLabs/gitoxide · error
cannot delete because another worktree has it checked out
Error message
cannot delete {} because another worktree has it checked out What it means
During branch cleanup after a rebase, a rewritten branch that is planned for deletion (`expected.new.is_none()`) is found checked out in a different worktree. Deleting a branch referenced by another worktree's HEAD is not allowed, so the operation bails naming the branch via `expected.name.shorten()`. If it's checked out in the *same* repo/git-dir it is silently skipped (`continue`).
Solutions
- Remove the other worktree (`git worktree remove <path>`) or switch its HEAD off the branch, then retry.
- Detach the other worktree's HEAD so the branch is no longer checked out there.
- Skip deletion for that branch: keep the old branch instead of planning `new: None` for it.
- Run the rebase from (or after consolidating) the worktree that actually owns the branch.
Example fix
// before worktree::remove(repo, other_path)?; // branch still checked out -> bail // after detach_head_or_switch(other_worktree, "main")?; // release the branch worktree::remove(repo, other_path)?; edit.rebase(...)?; // deletion now succeeds
Defensive patterns
Strategy: validation
Validate before calling
for wt in repo.worktrees()? {
let wt_repo = wt.into_repo()?;
if wt_repo.git_dir() != repo.git_dir()
&& let Some(head_ref) = wt_repo.head()?.referent_name()
&& branches_planned_for_deletion.contains(&head_ref.to_owned()) {
// detach or remove this worktree first
}
}
Prevention
- Keep branch deletions out of rebase plans while other worktrees exist
- Detach secondary worktrees when running history rewrites
- Inventory `git worktree list` before automated history edits
When it happens
Trigger: Running a rebase edit that rewrites and deletes branches while a separate linked worktree has `HEAD` pointed at one of the to-be-deleted old branch names — i.e. `worktree_repo.git_dir() != repo.git_dir()` and the planned new branch is `None`.
Common situations: Multi-worktree setups where an old feature branch checked out in a second worktree gets rewritten/deleted by a rebase run from the main worktree; CI or scripts operating on the same repository from multiple worktrees.
Related errors
- a detached checked-out root commit cannot be removed
- Need a worktree to clean, this is a bare repository
- JSON output isn't implemented yet
- rebase todo requires at least one -x/--hide revision when…
- the hidden and visible revisions have no editable fork point
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/332d0579394cc939.
Report an issue: GitHub.
Appendix: source
Thrown at gix-tix/src/edit/rebase.rs:2913
for worktree_repo in repos {
if !seen.insert(worktree_repo.git_dir().to_owned()) {
continue;
}
let Ok(head) = worktree_repo.head() else {
continue;
};
let Some(old) = head.id().map(gix::Id::detach) else {
continue;
};
let planned = head.referent_name().and_then(|name| {
expected_refs.and_then(|refs| refs.iter().find(|expected| expected.name.as_bstr() == name.as_bstr()))
});
let new = match planned {
Some(expected) if expected.new.is_none() => {
if worktree_repo.git_dir() == repo.git_dir() {
continue;
}
anyhow::bail!(
"cannot delete {} because another worktree has it checked out",
expected.name.shorten()
);
}
Some(expected) => Some(expected.new),
None => rewritten.get(&old).copied(),
};
let Some(new) = new else { continue };
if worktree_repo.workdir().is_none() && worktree_repo.is_bare() {
continue;
}
let old_tree = worktree_repo.find_commit(old)?.tree_id()?.detach();
let new_tree = match new {
Some(new) => repo.find_commit(new)?.tree_id()?.detach(),
None if worktree_repo.head()?.referent_name().is_some() => repo.empty_tree().id,
None => anyhow::bail!("a detached checked-out root commit cannot be removed"),
};
if old_tree == new_tree {View on GitHub (pinned to e73179060b)