jesseduffield/lazygit · warning

Cannot fast-forward a branch whose remote is not registered

Error message

Cannot fast-forward a branch whose remote is not registered locally

What it means

Thrown by BranchesController.fastForward when the selected branch tracks an upstream whose remote-tracking ref does not exist in the local repository (RemoteBranchStoredLocally() is false). lazygit fast-forwards by merging from the locally stored remote branch (e.g. origin/foo), so it refuses when that ref is missing even though upstream is configured. It is a precondition guard, not a git failure.

Source

Thrown at pkg/gui/controllers/branches_controller.go:663

		Items: []*types.MenuItem{localDeleteItem, remoteDeleteItem, deleteBothItem},
	})
}

func (self *BranchesController) merge() error {
	selectedBranchName := self.context().GetSelected().Name
	return self.c.Helpers().MergeAndRebase.MergeRefIntoCheckedOutBranch(selectedBranchName)
}

func (self *BranchesController) rebase(branch *models.Branch) error {
	return self.c.Helpers().MergeAndRebase.RebaseOntoRef(branch.Name)
}

func (self *BranchesController) fastForward(branch *models.Branch) error {
	if !branch.IsTrackingRemote() {
		return errors.New(self.c.Tr.FwdNoUpstream)
	}
	if !branch.RemoteBranchStoredLocally() {
		return errors.New(self.c.Tr.FwdNoLocalUpstream)
	}
	if branch.IsAheadForPull() {
		return errors.New(self.c.Tr.FwdCommitsToPush)
	}

	action := self.c.Tr.Actions.FastForwardBranch
	worktree, ok := self.worktreeForBranch(branch)

	return self.c.WithInlineStatus(branch, types.ItemOperationFastForwarding, context.LOCAL_BRANCHES_CONTEXT_KEY, func(task gocui.Task) error {
		if ok {
			self.c.LogAction(action)

			worktreeGitDir := ""
			worktreePath := ""
			// if it is the current worktree path, no need to specify the path
			if !worktree.IsCurrent {
				worktreeGitDir = worktree.GitDir
				worktreePath = worktree.Path

View on GitHub (pinned to c477a2959b)

Solutions

  1. Run 'git fetch <remote>' (or press 'f' in the branches panel after fetching) so refs/remotes/<remote>/<branch> exists locally
  2. Verify the upstream configuration with 'git branch -vv' and the remote ref with 'git branch -r | grep <branch>'
  3. If the remote was renamed, update the upstream: 'git branch --set-upstream-to=<new-remote>/<branch>'
  4. If you actually have local commits to integrate, use rebase or merge instead of fast-forward

Example fix

# before
git branch --set-upstream-to=origin/feature feature   # upstream set, but ref never fetched; 'f' errors
# after
git fetch origin
git branch --set-upstream-to=origin/feature feature
Defensive patterns

Strategy: validation

Validate before calling

// Before invoking fast-forward, ensure the remote-tracking ref exists locally:
// (Go, mirroring the model checks in branches_controller.go)
func canFastForward(branch *models.Branch, remotes []*models.Remote) error {
	if !branch.IsTrackingRemote() {
		return fmt.Errorf("branch %s has no upstream", branch.Name)
	}
	if !branch.RemoteBranchStoredLocally() {
		return fmt.Errorf("run 'git fetch %s' first: remote branch not stored locally", branch.RemoteName())
	}
	if branch.IsAheadForPull() {
		return fmt.Errorf("branch %s is ahead of upstream; push or pull first", branch.Name)
	}
	return nil
}

Prevention

When it happens

Trigger: Pressing the fast-forward key ('f') on a branch where branch.IsTrackingRemote() is true but refs/remotes/<remote>/<upstream> is absent from the local refs. Typical after a shallow/partial clone, after 'git remote prune' removed stale remote refs, or when the upstream was set with 'git branch --set-upstream-to' but never fetched.

Common situations: Fresh clones with limited refspecs, repositories where the remote was renamed (upstream points at old remote name), or CI checkouts with --single-branch so other remote branches were never fetched.

Related errors


AI-assisted analysis of jesseduffield/lazygit@c477a2959b (2026-08-15). Data as JSON: /api/errors/a33414796a32f0e9. Report an issue: GitHub.