{"record":{"id":"5e46c64df5792d45","repo":"jesseduffield/lazygit","slug":"expected-exactly-one-fixup-hash-found-d","errorCode":null,"errorMessage":"Expected exactly one fixup hash, found %d","messagePattern":"Expected exactly one fixup hash, found (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/utils/rebase_todo.go","lineNumber":263,"sourceCode":"}\n\nfunc moveFixupCommitDown(todos []todo.Todo, originalHash string, fixupHash string, changeToFixup bool) ([]todo.Todo, error) {\n\tisOriginal := func(t todo.Todo) bool {\n\t\treturn (t.Command == todo.Pick || t.Command == todo.Merge) && equalHash(t.Commit, originalHash)\n\t}\n\n\tisFixup := func(t todo.Todo) bool {\n\t\treturn t.Command == todo.Pick && equalHash(t.Commit, fixupHash)\n\t}\n\n\toriginalHashCount := lo.CountBy(todos, isOriginal)\n\tif originalHashCount != 1 {\n\t\treturn nil, fmt.Errorf(\"Expected exactly one original hash, found %d\", originalHashCount)\n\t}\n\n\tfixupHashCount := lo.CountBy(todos, isFixup)\n\tif fixupHashCount != 1 {\n\t\treturn nil, fmt.Errorf(\"Expected exactly one fixup hash, found %d\", fixupHashCount)\n\t}\n\n\t_, fixupIndex, _ := lo.FindIndexOf(todos, isFixup)\n\t_, originalIndex, _ := lo.FindIndexOf(todos, isOriginal)\n\n\tnewTodos := MoveElement(todos, fixupIndex, originalIndex+1)\n\n\tif changeToFixup {\n\t\tnewTodos[originalIndex+1].Command = todo.Fixup\n\t}\n\n\treturn newTodos, nil\n}\n\nfunc RemoveUpdateRefsForCopiedBranch(fileName string, commentChar byte) error {\n\ttodos, err := ReadRebaseTodoFile(fileName, commentChar)\n\tif err != nil {\n\t\treturn err","sourceCodeStart":245,"sourceCodeEnd":281,"githubUrl":"https://github.com/jesseduffield/lazygit/blob/c477a2959b229fbf3284be0d4d2904ab61ec3c94/pkg/utils/rebase_todo.go#L245-L281","documentation":"Companion check in moveFixupCommitDown: it counts todos with command Pick and the fixup commit's hash and requires exactly one. Zero means the fixup commit being moved is not in the todo file; two or more means duplicated pick entries for it. The strict count protects against moving the wrong entry onto the original commit.","triggerScenarios":"Squashing a fixup during interactive rebase when the fixup commit is missing from .git-rebase-todo (already applied/dropped) or appears as multiple pick lines.","commonSituations":"Same class as the original-hash error: externally modified todo files, stale lazygit models after a conflict resolution step, duplicated picks after rebase continuations.","solutions":["Verify the fixup commit still exists as a single 'pick <hash>' line in .git-rebase-todo","Remove duplicate pick lines for that hash or restart the rebase if the file is inconsistent","If 'found 0', the fixup was already applied — refresh lazygit before attempting the squash"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"# sanity check before fixup: fixup hash picked exactly once\ngrep -cE \"^pick ${FULL_HASH}\" .git/rebase-merge/git-rebase-merge/git-rebase-todo 2>/dev/null || grep -cE \"^pick ${FULL_HASH}\" .git/rebase-merge/git-rebase-todo  # want exactly 1","typeGuard":null,"tryCatchPattern":"Catch and branch on the count: 0 → fixup already applied, refresh and skip; 2+ → de-duplicate pick lines in the todo, then retry.","preventionTips":["Keep the todo file free of duplicate picks before attempting squash operations","Refresh lazygit's view after each rebase continuation"],"tags":["lazygit","rebase","fixup","squash","git-rebase-todo"],"backgroundTag":null,"analyzedSha":"c477a2959b229fbf3284be0d4d2904ab61ec3c94","analyzedAt":"2026-08-15T08:34:32.451Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}