{"record":{"id":"f4ab9e04618cf088","repo":"jesseduffield/lazygit","slug":"cannot-squash-commits-in-current-branch-the-head","errorCode":null,"errorMessage":"Cannot squash commits in current branch: the HEAD commit is a merge commit or is present on the main branch.","messagePattern":"Cannot squash commits in current branch: the HEAD commit is a merge commit or is present on the main branch\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pkg/gui/controllers/local_commits_controller.go","lineNumber":1640,"sourceCode":"\t\t\t\tThen: func() error {\n\t\t\t\t\tif err == nil {\n\t\t\t\t\t\tself.context().SetSelectedLineIdx(targetIdx)\n\t\t\t\t\t\tself.c.PostRefreshUpdate(self.context())\n\t\t\t\t\t}\n\t\t\t\t\treturn nil\n\t\t\t\t},\n\t\t\t})\n\t})\n}\n\nfunc (self *LocalCommitsController) findCommitForSquashFixupsInCurrentBranch() (*models.Commit, int, error) {\n\tcommits := self.c.Model().Commits\n\t_, index, ok := lo.FindIndexOf(commits, func(c *models.Commit) bool {\n\t\treturn c.IsMerge() || c.Status == models.StatusMerged\n\t})\n\n\tif !ok || index == 0 {\n\t\treturn nil, -1, errors.New(self.c.Tr.CannotSquashCommitsInCurrentBranch)\n\t}\n\n\treturn commits[index-1], index - 1, nil\n}\n\n// Anticipate how many commits above the selectedIdx are going to get squashed\n// by the SquashAllAboveFixupCommits call, so that we can adjust the selection\n// afterwards. Let's hope we're matching git's behavior correctly here.\nfunc countSquashableCommitsAbove(commits []*models.Commit, selectedIdx int, rebaseStartIdx int) int {\n\tresult := 0\n\n\t// For each commit _above_ the selection, ...\n\tfor i, commit := range commits[0:selectedIdx] {\n\t\t// ... see if it is a fixup commit, and get the base subject it applies to\n\t\tif baseSubject, isFixup := helpers.IsFixupCommit(commit.Name); isFixup {\n\t\t\t// Then, for each commit after the fixup, up to and including the\n\t\t\t// rebase start commit, see if we find the base commit\n\t\t\tfor _, baseCommit := range commits[i+1 : rebaseStartIdx+1] {","sourceCodeStart":1622,"sourceCodeEnd":1658,"githubUrl":"https://github.com/jesseduffield/lazygit/blob/c477a2959b229fbf3284be0d4d2904ab61ec3c94/pkg/gui/controllers/local_commits_controller.go#L1622-L1658","documentation":"Returned by findCommitForSquashFixupsInCurrentBranch, the 'squash all fixup commits above' helper. It uses the same predicate as the quick-start rebase check — the first commit that IsMerge() or has Status == StatusMerged must exist below index 0 — because squashing fixups internally starts an interactive rebase from that commit. When no such base exists (or it is HEAD), the operation is impossible in the current branch.","triggerScenarios":"Invoking squash-fixups-in-current-branch when lo.FindIndexOf(commits, IsMerge || StatusMerged) yields !ok or index == 0 — i.e. HEAD is a merge commit or is already merged into the main branch.","commonSituations":"Branch fully merged to main with only fixup commits above; HEAD is a merge commit (e.g. after merging a PR locally); shallow clone hiding the merge base.","solutions":["Start an interactive rebase manually from a chosen commit and squash the fixups there.","If HEAD is a merge commit, reset or rebase past it first, then retry.","Unguard/deepen the clone (git fetch --unshallow) so a usable base commit is visible."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"_, index, ok := lo.FindIndexOf(self.c.Model().Commits, func(c *models.Commit) bool {\n    return c.IsMerge() || c.Status == models.StatusMerged\n})\nif !ok || index == 0 {\n    // disable squash-fixups action for this branch\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Gate the squash-fixups menu item with the same predicate used by findCommitForSquashFixupsInCurrentBranch.","Avoid merging to main before cleaning up fixup commits.","Use explicit interactive rebase from a selected commit when the guard trips."],"tags":["rebase","fixup","squash","history"],"backgroundTag":null,"analyzedSha":"c477a2959b229fbf3284be0d4d2904ab61ec3c94","analyzedAt":"2026-08-15T08:34:32.451Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}