jesseduffield/lazygit · warning

Cannot fast-forward a branch with commits to push

Error message

Cannot fast-forward a branch with commits to push

What it means

Thrown by BranchesController.fastForward when branch.IsAheadForPull() is true, i.e. the branch has commits that exist locally but not on its upstream. Fast-forward only moves a branch forward to match the remote; it never discards or reconciles local commits, so lazygit refuses rather than risk divergence being masked. This guard runs after the no-upstream and no-local-upstream checks.

Source

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

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
			}

			err := self.c.Git().Sync.Pull(

View on GitHub (pinned to c477a2959b)

Solutions

  1. Push the local commits first ('git push'), then fast-forward is a no-op/succeeds
  2. If the remote moved too, use 'pull' (rebase or merge) instead of fast-forward
  3. If the local commits are unwanted, reset to the upstream: 'git reset --hard @{u}' (destroys local commits)

Example fix

# before: branch is ahead, pressing 'f' errors
# after: choose an integration action instead
 git push            # publish local commits
# or
 git pull --rebase   # integrate remote changes
Defensive patterns

Strategy: validation

Validate before calling

// Check ahead/behind before fast-forwarding:
if branch.IsAheadForPull() {
    // choose push or pull --rebase instead of fast-forward
    return pushOrRebase(branch)
}

Prevention

When it happens

Trigger: Pressing 'f' (fast-forward) on a branch that is ahead of its upstream — you committed locally but did not push, or you rebased onto something newer and the remote ref is behind.

Common situations: Working offline with local commits, a shared branch you committed to directly, or after amending an already-pushed commit so the branch appears ahead.

Related errors


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