jesseduffield/lazygit · warning
Cannot start interactive rebase: the HEAD commit is a merge
Error message
Cannot start interactive rebase: the HEAD commit is a merge commit or is present on the main branch, so there is no appropriate base commit to start the rebase from. You can start an interactive rebase from a specific commit by selecting the commit and pressing `{{.editKey}}`. What it means
Returned by findCommitForQuickStartInteractiveRebase when scanning Model().Commits finds no commit satisfying IsMerge() || Status == StatusMerged, or the first such commit is at index 0 (it is HEAD). Quick-starting an interactive rebase needs a safe base commit below the first merge/main-branch commit; when HEAD itself is a merge or already on the main line, there is no such base, so the user is told to select a commit and press edit instead.
Source
Thrown at pkg/gui/controllers/local_commits_controller.go:1079
if len(todos) > 0 {
return self.updateTodos(todo.Edit, todos)
}
return nil
}})
})
}
func (self *LocalCommitsController) findCommitForQuickStartInteractiveRebase() (*models.Commit, error) {
commit, index, ok := lo.FindIndexOf(self.c.Model().Commits, func(c *models.Commit) bool {
return c.IsMerge() || c.Status == models.StatusMerged
})
if !ok || index == 0 {
errorMsg := utils.ResolvePlaceholderString(self.c.Tr.CannotQuickStartInteractiveRebase, map[string]string{
"editKey": self.c.UserConfig().Keybinding.Universal.Edit.String(),
})
return nil, errors.New(errorMsg)
}
return commit, nil
}
func (self *LocalCommitsController) pick(selectedCommits []*models.Commit) error {
if self.isRebasing() {
return self.updateTodos(todo.Pick, selectedCommits)
}
panic("should be disabled when not rebasing")
}
func (self *LocalCommitsController) interactiveRebase(commits []*models.Commit, action todo.TodoCommand, startIdx int, endIdx int) error {
return self.interactiveRebaseWithFlag(commits, action, startIdx, endIdx, "")
}
func (self *LocalCommitsController) interactiveRebaseWithFlag(commits []*models.Commit, action todo.TodoCommand, startIdx int, endIdx int, flag string) error {View on GitHub (pinned to c477a2959b)
Solutions
- Select a specific commit in the commits panel and press the edit key to start the interactive rebase from there.
- Fetch/unguard the full history if a shallow clone hides a suitable base commit.
- If all commits are merged to main, create a new branch and cherry-pick the work instead of rebasing the merged line.
Defensive patterns
Strategy: validation
Validate before calling
_, index, ok := lo.FindIndexOf(self.c.Model().Commits, func(c *models.Commit) bool {
return c.IsMerge() || c.Status == models.StatusMerged
})
if !ok || index == 0 {
// disable quick-start; require explicit commit selection
} Prevention
- Disable the quick-start rebase action via DisabledReason when no valid base commit exists.
- Teach users to start interactive rebases by selecting a commit and pressing edit.
- Detect shallow clones and warn that the merge base may be hidden.
When it happens
Trigger: Invoking the quick-start interactive rebase action (e.g. 'e'-based start-rebase flow / squash-fixup quick start) on a history where lo.FindIndexOf(commits, IsMerge || StatusMerged) returns !ok, or index == 0.
Common situations: Fresh branch whose every listed commit is already merged into main (all StatusMerged); HEAD is itself a merge commit; shallow history where the boundary is not visible.
Related errors
- Cannot squash commits in current branch: the HEAD commit is
- Expected exactly one merge commit with hash %s
- index outside of range of commits
- Feature not available for users using GPG. If you are using
- You are midway through another rebase operation. Please abor
AI-assisted analysis of jesseduffield/lazygit@c477a2959b (2026-08-15).
Data as JSON: /api/errors/7c348e3622c33c59.
Report an issue: GitHub.