gitbutlerapp/gitbutler · error
Destination commit must not be conflicted
Error message
Destination commit must not be conflicted
What it means
Guard in move_changes_between_commits: the destination commit currently carries conflicts, so moving changes into it would compound an unresolved state. The operation is refused until the user resolves the destination commit's conflicts, after which the move can be retried.
Solutions
- Resolve conflicts in the destination commit before moving changes into it
- Choose a non-conflicted destination commit
- Re-run the rebase resolving conflicts, then retry the move
Example fix
// before editor.move_changes_between_commits(src, conflicted_dst, changes, ctx)?; // after resolve_conflicts_in(conflicted_dst)?; editor.move_changes_between_commits(src, conflicted_dst, changes, ctx)?;
Defensive patterns
Strategy: validation
Validate before calling
let (_, dst) = editor.find_selectable_commit(dest_selector)?;
if dst.clone().attach(editor.repo()).is_conflicted() {
bail!("resolve destination conflicts first");
} Type guard
fn moveable(commit: &gix::Commit) -> bool { !commit.clone().attach(commit.repo).is_conflicted() } Try / catch
match editor.move_changes_between_commits(src, dst, changes, ctx) {
Err(e) if e.to_string().contains("Destination commit must not be conflicted") => resolve_then_retry(dst),
other => other,
} Prevention
- Check destination conflict state (pre- and post-rebase) before moves
- Resolve conflicts before pulling changes into a commit
- Prefer conflict-free destinations when automating moves
When it happens
Trigger: move_changes_between_commits finds the (rebased) destination commit conflicted via is_conflicted() before applying the changes to its tree.
Common situations: Moving changes into a commit that sits behind a conflict introduced by a rebase; destination commit already carried conflict markers from a prior operation.
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
- Source commit must not be conflicted
- Cannot amend a conflicted commit
- Branch ' ' already exists
- Branch ' ' cannot be created: the target commit ( ) already…
- cannot amend into : the commit is immutable (not part of a…
AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18).
Data as JSON: /api/errors/4819d4684d14c8ab.
Report an issue: GitHub.
Appendix: source
Thrown at crates/but-workspace/src/commit/move_changes.rs:99
if !dropped_diffs.is_empty() {
bail!("Failed to extract described changes from source commit");
}
let new_source_commit_id = {
let mut new_source_commit = source_commit.clone();
new_source_commit.tree = source_tree_without_changes_id;
editor.new_commit(new_source_commit, DateMode::CommitterUpdateAuthorKeep)?
};
editor.replace(source_selector, Step::new_pick(new_source_commit_id))?;
// Rebase and get potentially rebased destination commit
let mut editor = editor.rebase()?.into_editor();
let (_, rebased_destination_commit) = editor.find_selectable_commit(destination_selector)?;
let destination_tree_id = {
let rebased_destination_commit = rebased_destination_commit.clone().attach(editor.repo());
if rebased_destination_commit.is_conflicted() {
bail!("Destination commit must not be conflicted")
}
rebased_destination_commit.tree
};
let destination_tree_with_changes = {
let repo = editor.repo();
let (fail_fast_options, conflict_kind) = repo.merge_options_fail_fast()?;
let mut merge_result = repo.merge_trees(
source_tree_without_changes_id,
source_tree_id,
destination_tree_id,
Default::default(),
fail_fast_options,
)?;
if merge_result.has_unresolved_conflicts(conflict_kind) {
bail!("Failed to apply changes to destination commit - merge conflict");
}View on GitHub (pinned to 58e5313667)