jesseduffield/lazygit · error

Expected exactly one original hash, found %d

Error message

Expected exactly one original hash, found %d

What it means

Returned by moveFixupCommitDown when squashing a fixup: it counts todos whose command is Pick or Merge with the original commit's hash and requires exactly one. Any count other than 1 — zero (original not in todo) or more than one (original appears as both a pick and a 'merge -C' entry, or duplicated picks) — aborts with this error rather than guessing which entry to target.

Source

Thrown at pkg/utils/rebase_todo.go:258

	if err != nil {
		return err
	}

	return WriteRebaseTodoFile(fileName, newTodos, commentChar)
}

func moveFixupCommitDown(todos []todo.Todo, originalHash string, fixupHash string, changeToFixup bool) ([]todo.Todo, error) {
	isOriginal := func(t todo.Todo) bool {
		return (t.Command == todo.Pick || t.Command == todo.Merge) && equalHash(t.Commit, originalHash)
	}

	isFixup := func(t todo.Todo) bool {
		return t.Command == todo.Pick && equalHash(t.Commit, fixupHash)
	}

	originalHashCount := lo.CountBy(todos, isOriginal)
	if originalHashCount != 1 {
		return nil, fmt.Errorf("Expected exactly one original hash, found %d", originalHashCount)
	}

	fixupHashCount := lo.CountBy(todos, isFixup)
	if fixupHashCount != 1 {
		return nil, fmt.Errorf("Expected exactly one fixup hash, found %d", fixupHashCount)
	}

	_, fixupIndex, _ := lo.FindIndexOf(todos, isFixup)
	_, originalIndex, _ := lo.FindIndexOf(todos, isOriginal)

	newTodos := MoveElement(todos, fixupIndex, originalIndex+1)

	if changeToFixup {
		newTodos[originalIndex+1].Command = todo.Fixup
	}

	return newTodos, nil
}

View on GitHub (pinned to c477a2959b)

Solutions

  1. Inspect .git-rebase-todo and remove the duplicate/contradictory entry for that hash, then retry the fixup
  2. Abort the rebase and redo it, squashing before the todo file accumulates duplicates
  3. Check the reported count: 'found 0' means the original commit isn't part of this rebase at all (wrong base), 'found 2+' means duplication
Defensive patterns

Strategy: validation

Validate before calling

# sanity check before fixup: original hash appears exactly once as pick or merge -C
grep -cE "^(pick|merge -C) ${FULL_HASH}" .git/rebase-merge/git-rebase-todo  # want exactly 1

Try / catch

Catch and inspect the count: 0 means wrong base or already-applied original (restart rebase), 2+ means duplicate entries (clean the todo file, then retry).

Prevention

When it happens

Trigger: Pressing fixup/squash in lazygit during an interactive rebase where the original commit is represented multiple times (e.g. a 'merge -C <hash>' line plus a 'pick <hash>') or is absent from the todo because it was already applied or dropped.

Common situations: Squashing onto a merge commit whose hash also appears in a merge -C line; rebases with duplicated entries after conflict resolution; todo files rewritten by external tooling leaving duplicate picks.

Related errors


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