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
- Push the local commits first ('git push'), then fast-forward is a no-op/succeeds
- If the remote moved too, use 'pull' (rebase or merge) instead of fast-forward
- 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
- Treat fast-forward as remote-only sync: publish local commits with push first
- In scripts, compare rev-list counts ahead/behind before 'git merge --ff-only'
- Prefer 'git pull --ff-only' semantics and handle divergence explicitly
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
- Cannot fast-forward a branch with no upstream
- Cannot fast-forward a branch whose remote is not registered
- Git version must be at least %s. Please upgrade your git ver
- Lazygit does not support bare repos.
- unexpected git output
AI-assisted analysis of jesseduffield/lazygit@c477a2959b (2026-08-15).
Data as JSON: /api/errors/9def6fec77e110ba.
Report an issue: GitHub.