gitbutlerapp/gitbutler · error

Target branch {target_ref_name} not found

Error message

Target branch {target_ref_name} not found

What it means

During land, after fetch_target_remote, the target is resolved as refs/remotes/<fetch_remote>/<target_branch> in decide_land_outcome. If that remote-tracking ref is absent — the target branch does not exist under the fetch remote, the remote name is wrong, or the fetch produced no such ref — the land aborts before any push.

Source

Thrown at crates/but-api/src/land/merge.rs:46

/// rename-aware merge commit. Conflicts bail here, before anything is pushed or moved.
pub(super) fn decide_land_outcome(
    repo: &gix::Repository,
    branch_name: &str,
    fetch_remote_name: &str,
    target_branch_name: &str,
    no_ff: bool,
) -> anyhow::Result<LandOutcome> {
    let feature_ref_name = format!("refs/heads/{branch_name}");
    let feature_oid = repo
        .try_find_reference(&feature_ref_name)?
        .ok_or_else(|| anyhow::anyhow!("Branch {branch_name} not found"))?
        .into_fully_peeled_id()?
        .detach();

    let target_ref_name = format!("refs/remotes/{fetch_remote_name}/{target_branch_name}");
    let target_oid = repo
        .try_find_reference(&target_ref_name)?
        .ok_or_else(|| anyhow::anyhow!("Target branch {target_ref_name} not found"))?
        .into_fully_peeled_id()?
        .detach();

    // No common ancestor: refuse rather than merge two unrelated histories onto the target.
    let Some(merge_base) = super::merge_base_opt(repo, feature_oid, target_oid)? else {
        bail!(
            "Cannot land {branch_name}: it shares no history with {fetch_remote_name}/{target_branch_name}"
        );
    };

    if merge_base == feature_oid {
        return Ok(LandOutcome::AlreadyIntegrated);
    }
    if merge_base == target_oid && !no_ff {
        return Ok(LandOutcome::FastForward {
            feature_oid,
            target_oid,
        });

View on GitHub (pinned to 2497b8007a)

Solutions

  1. Confirm the tracking ref: git fetch <remote> && git branch -r --list '<remote>/<target>'.
  2. Update the workspace target branch to a branch that exists on the remote (GitButler target/base-branch settings).
  3. If the upstream branch was renamed, retarget the workspace to the new name before re-running land.

Example fix

git fetch origin
git branch -r --list 'origin/*'   # confirm the target exists upstream
# retarget the workspace to the real default branch, then:
but land feat/auth
Defensive patterns

Strategy: validation

Validate before calling

fn target_tracking_ref_exists(
    repo: &gix::Repository,
    fetch_remote: &str,
    target_branch: &str,
) -> anyhow::Result<bool> {
    Ok(repo
        .try_find_reference(&format!("refs/remotes/{fetch_remote}/{target_branch}"))?
        .is_some())
}

Prevention

When it happens

Trigger: branch_land where the configured target branch has no refs/remotes/<remote>/<target> ref: upstream branch deleted or renamed (main vs master), base-branch data pointing at an old remote name, or a fetch that created no tracking ref for that branch.

Common situations: Upstream default branch renamed while the workspace still targets the old name; remote pruned; target configured against a fork remote that lacks the branch; offline fetch that silently skipped ref updates.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@2497b8007a (2026-08-17). Data as JSON: /api/errors/d9b4c4d5d8da5b59. Report an issue: GitHub.