gitbutlerapp/gitbutler · error · anyhow::Error

remote branch '{target_branch_ref}' not found

Error message

remote branch '{target_branch_ref}' not found

What it means

Changing the target/base branch looks up the remote-tracking reference by name via repo.try_find_reference. If no such reference exists locally (refs/remotes/<remote>/<branch> is absent), the lookup returns None and the target change is rejected with this error.

Source

Thrown at crates/gitbutler-branch-actions/src/base.rs:184

            .as_ref()
            .is_some_and(|target_ref| target_ref.to_string() == target_branch_ref.to_string());
        (
            workspace_ref_exists && project_meta.target_commit_id.is_some() && target_ref_matches,
            project_meta.target_ref,
        )
    } else {
        (false, None)
    };

    // if target exists, and it is the same as the requested branch, we should go back
    if existing_target_ref_matches {
        return go_back_to_integration(ctx, perm);
    }

    // lookup a branch by name
    let mut target_branch = repo
        .try_find_reference(target_branch_ref.to_string().as_str())?
        .ok_or(anyhow!("remote branch '{target_branch_ref}' not found"))?;

    let target_branch_head = target_branch
        .peel_to_commit()
        .context(format!(
            "failed to peel branch {target_branch_ref} to commit"
        ))?
        .id;

    let mut current_head = repo.head().context("Failed to get HEAD reference")?;
    let current_head_commit = current_head
        .peel_to_commit()
        .context("Failed to peel HEAD reference to commit")?
        .id;

    // calculate the commit as the merge-base between HEAD in ctx and this target commit
    let target_commit_oid = repo
        .merge_base(current_head_commit, target_branch_head)
        .map(|id| id.detach())

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Fetch first: `git fetch --all --prune`, then retry the target command
  2. Verify the exact remote-tracking ref exists: `git branch -r` (or `git ls-remote origin`)
  3. Use the fully qualified remote and branch, e.g. `but config target origin/main`

Example fix

# before
but config target orgin/main   # typo / never fetched
# after
git fetch --prune
but config target origin/main
Defensive patterns

Strategy: validation

Validate before calling

let exists = repo
    .rev_parse_single(format!("refs/remotes/{remote}/{branch}"))
    .is_ok();
anyhow::ensure!(exists, "remote branch not fetched yet; run git fetch first");

Try / catch

Catch this error, run `git fetch --all --prune`, and retry the target-branch operation once.

Prevention

When it happens

Trigger: Setting the target to a remote branch that was never fetched (fresh clone, shallow state), a typo in the remote/branch name, or the branch was deleted upstream and the tracking ref pruned away.

Common situations: Forgetting `git fetch` before setting the target; using the wrong remote name ('github/main' vs 'origin/main'); branch renamed or deleted on the remote.

Related errors


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