gitbutlerapp/gitbutler · error

Cannot unapply workspace reference by checking out conflicte

Error message

Cannot unapply workspace reference by checking out conflicted commit at '{}'

What it means

The workspace-reference flavor of the conflicted-commit guard: when unapplying the workspace reference itself, the commit that would be checked out (RefToCheckout.commit_id) is conflicted. The message names the ref whose commit is conflicted so users can locate it. As with the sibling error, resolve conflicts first — no checkout happens when this fires.

Source

Thrown at crates/but-workspace/src/branch/unapply.rs:752

    /// Check out `ref_to_checkout` using the workspace traversal entrypoint as the
    /// current worktree/index source.
    ///
    /// `ws` must be the workspace projection for the currently checked-out `HEAD`.
    /// Its graph entrypoint is therefore the commit the index and worktree are
    /// expected to match before checkout. This matters when `HEAD` points at a
    /// stack segment inside the workspace rather than the workspace tip.
    ///
    /// The helper only updates the index/worktree according to `options`; callers
    /// remain responsible for any subsequent `HEAD`, reference, metadata, and
    /// projection updates.
    fn safe_checkout_ref_to_checkout(
        repo: &gix::Repository,
        ref_to_checkout: &RefToCheckout,
        options: but_core::worktree::checkout::Options,
    ) -> anyhow::Result<but_core::worktree::checkout::Outcome> {
        if but_core::Commit::from_id(ref_to_checkout.commit_id.attach(repo))?.is_conflicted() {
            bail!(
                "Cannot unapply workspace reference by checking out conflicted commit at '{}'",
                ref_to_checkout.ref_name.shorten()
            );
        }
        safe_checkout(repo, ref_to_checkout.commit_id, options)
    }

    /// Return the commit the workspace ref should point to when no workspace merge commit remains.
    ///
    /// A single remaining future tip is preferred. Otherwise, an empty workspace falls back to the
    /// resolved target or the workspace lower bound.
    fn commit_to_point_workspace_ref_to_after_unapply(
        ws: &but_graph::Workspace,
        future_workspace_tips: &[crate::commit::merge::Tip],
    ) -> anyhow::Result<gix::ObjectId> {
        if let Some(tip) = future_workspace_tips.first() {
            return Ok(tip.commit_id);
        }

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Resolve conflicts on the named ref (or remove/undo the conflicted commit) and retry the workspace unapply.
  2. Choose a different target to switch to by fixing the workspace state (integrate or unapply conflicted stacks first).
  3. Fall back to GitButler's UI flow, which forces conflict resolution before workspace dissolution.
Defensive patterns

Strategy: validation

Validate before calling

use but_core::Commit;
let ref_to_checkout = ref_to_checkout_after_workspace_unapply(&ws)?;
if Commit::from_id(ref_to_checkout.commit_id.attach(repo))?.is_conflicted() {
    // the commit we would land on is conflicted: resolve or pick another target first
    return prompt_conflict_resolution();
}

Try / catch

match unapply(repo, meta, &ws, ws_ref, opts) {
    Err(err) if err.to_string().contains("conflicted commit at") => {
        ui::error("Resolve conflicts on the target branch before dissolving the workspace");
        Ok(default_outcome())
    }
    other => other,
}

Prevention

When it happens

Trigger: Calling unapply on the workspace reference (e.g. with a PreventUnnecessaryWorkspaceReferences disposition) when ref_to_checkout_after_workspace_unapply() selected a commit that but_core reports as conflicted.

Common situations: Dissolving a workspace whose remaining tip or target commit still contains conflict markers; unapplying the workspace ref right after a conflicted sync.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20). Data as JSON: /api/errors/06eae818c234e3df. Report an issue: GitHub.