gitbutlerapp/gitbutler · error

failed to find branch {target_branch_refname}

Error message

failed to find branch {target_branch_refname}

What it means

Thrown by GitContextExt::git_test_push (crates/gitbutler-git/src/context.rs). The helper builds refs/remotes/{remote_name}/{branch_name} and calls repo.try_find_reference() on it; if that ref does not exist locally it bails with this message. The ref is used as the source commit for a throwaway test-push branch, so a missing remote-tracking ref aborts the whole connectivity/permission test.

Source

Thrown at crates/gitbutler-git/src/context.rs:106

            force_push_protection,
            refspec,
            askpass_broker,
            push_opts,
        )
    }

    fn git_test_push(
        &self,
        remote_name: &str,
        branch_name: &str,
        askpass: Option<Option<StackId>>,
    ) -> Result<()> {
        let target_branch_refname: gix::refs::FullName =
            format!("refs/remotes/{remote_name}/{branch_name}").try_into()?;
        let repo = self.repo.get()?;
        let mut branch = repo
            .try_find_reference(&target_branch_refname.to_string())?
            .ok_or(anyhow!("failed to find branch {target_branch_refname}"))?;

        let commit_id = branch.peel_to_commit()?.id;
        let branch_name = format!("test-push-{}", now_ms());
        let refname: gix::refs::FullName =
            format!("refs/remotes/{remote_name}/{branch_name}").try_into()?;

        self.push(
            commit_id,
            refname.clone(),
            false,
            false,
            None,
            askpass,
            vec![],
        )
        .map_err(|err| anyhow!(err.to_string()))?;

        let empty_refspec = Some(format!(":refs/heads/{branch_name}"));

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Fetch the remote first so refs/remotes/{remote}/{branch} exists: ctx.fetch(remote_name, None) before git_test_push
  2. Verify the ref locally: `git branch -r --list '{remote}/{branch}'` (or repo.try_find_reference) and fix the remote/branch arguments if missing
  3. If the branch was deleted upstream, test against a branch that exists, e.g. the repository default branch
  4. For --single-branch clones, re-clone or configure the refspec to fetch the needed branch

Example fix

// before
ctx.git_test_push(&remote_name, &branch_name, askpass)?;

// after: make sure the remote-tracking ref exists before testing
ctx.fetch(&remote_name, None)?;
let refname = format!("refs/remotes/{remote_name}/{branch_name}");
if ctx.repo.get()?.try_find_reference(&refname)?.is_none() {
    anyhow::bail!("{refname} not found after fetch — check remote/branch names");
}
ctx.git_test_push(&remote_name, &branch_name, askpass)?;
Defensive patterns

Strategy: validation

Validate before calling

ctx.fetch(&remote_name, None)?; // materialize refs/remotes/<remote>/<branch>
let refname = format!("refs/remotes/{remote_name}/{branch_name}");
let repo = ctx.repo.get()?;
if repo.try_find_reference(&refname)?.is_none() {
    // pick a branch that exists, e.g. the default branch, instead of failing later
    anyhow::bail!("{refname} missing — branch not fetched or wrong remote");
}

Try / catch

match ctx.git_test_push(&remote_name, &branch_name, askpass) {
    Ok(()) => Ok(()),
    Err(err) if err.to_string().contains("failed to find branch") => {
        // remote-tracking ref absent: fetch once and retry with the default branch
        ctx.fetch(&remote_name, None)?;
        ctx.git_test_push(&remote_name, default_branch, askpass)
    }
    Err(err) => Err(err),
}

Prevention

When it happens

Trigger: Calling git_test_push(remote_name, branch_name) before ever fetching that remote; passing a branch name that only exists on another remote or was deleted upstream; passing a wrong remote name (typo, or remote only configured in another clone); shallow/partial clones that never wrote refs/remotes/<remote>/<branch>.

Common situations: Auth-flow test immediately after adding a project before the first fetch completed; the target branch was renamed or deleted on the server; users with multiple remotes (origin + fork) picking the wrong one; CI environments where the clone was created with --single-branch so other remote-tracking refs are absent.

Related errors


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