gitbutlerapp/gitbutler · error

Failed to apply changes to destination commit - merge…

Error message

Failed to apply changes to destination commit - merge conflict

What it means

The three-way merge that applies the extracted changes onto the destination tree produced unresolved conflicts, so the move would corrupt the destination commit. The library bails instead of writing the conflicted tree.

Solutions

  1. Manually apply the change to the destination commit (edit + restage) and only remove it from the source
  2. Move the changes to an adjacent commit where merge context is closer
  3. Reduce the size/scope of the moved hunks so they merge cleanly

Example fix

// before
editor.move_changes_between_commits(src, dst, big_hunk, ctx)?; // merge conflict
// after
let smaller = split_hunk(big_hunk);
editor.move_changes_between_commits(src, dst, smaller, ctx)?;
Defensive patterns

Strategy: try-catch

Try / catch

match editor.move_changes_between_commits(src, dst, changes, ctx) {
    Err(e) if e.to_string().contains("merge conflict") => {
        // fall back to manual application: edit dst files, restage, then remove from src
    }
    other => other,
}

Prevention

When it happens

Trigger: move_changes_between_commits calls tree merge with fail_fast options and merge_result.has_unresolved_conflicts() returns true — i.e. the moved hunks overlap conflicting content in the destination commit.

Common situations: Moving a hunk into a commit where the same lines were modified differently; moving changes across many commits so context has drifted; binary or tightly-coupled files.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18). Data as JSON: /api/errors/75751ddebe5a15ae. Report an issue: GitHub.

Appendix: source

Thrown at crates/but-workspace/src/commit/move_changes.rs:116

        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");
        }

        merge_result.tree.write()?.detach()
    };

    let new_destination_commit_id = {
        let mut commit = rebased_destination_commit;
        commit.tree = destination_tree_with_changes;
        editor.new_commit(commit, DateMode::CommitterUpdateAuthorKeep)?
    };

    editor.replace(
        destination_selector,
        Step::new_pick(new_destination_commit_id),
    )?;

    let outcome = editor.rebase()?;

View on GitHub (pinned to 58e5313667)