Extract the check for a rescheduled rebase command into a helper

We are going to need it for recovering from lock errors during a rebase.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Stefan Haller
2026-11-08 14:54:41 +01:00
co-authored by Claude Opus 5.5
parent ed60806c04
commit 4486e8d149
2 changed files with 35 additions and 32 deletions
+1 -32
View File
@@ -430,38 +430,7 @@ func (self *CommitLoader) getConflictedCommitImpl(hashPool *utils.StringPool, to
return nil
}
// In certain cases, git reschedules commands that failed. One example is if
// a patch would overwrite an untracked file (another one is an "exec" that
// failed, but we don't care about that here because we dealt with exec
// already above). To detect this, compare the last command of the "done"
// file against the first command of "git-rebase-todo"; if they are the
// same, the command was rescheduled.
if len(doneTodos) > 0 && len(todos) > 0 && doneTodos[len(doneTodos)-1] == todos[0] {
// Command was rescheduled, no need to display it
return nil
}
// Older versions of git have a bug whereby, if a command is rescheduled,
// the last successful command is appended to the "done" file again. To
// detect this, we need to compare the second-to-last done entry against the
// first todo entry, and also compare the last done entry against the
// last-but-two done entry; this latter check is needed for the following
// case:
// pick A
// exec make test
// pick B
// exec make test
// If pick B fails with conflicts, then the "done" file contains
// pick A
// exec make test
// pick B
// and git-rebase-todo contains
// exec make test
// Without the last condition we would erroneously treat this as the exec
// command being rescheduled, so we wouldn't display our fake entry for
// "pick B".
if len(doneTodos) >= 3 && len(todos) > 0 && doneTodos[len(doneTodos)-2] == todos[0] &&
doneTodos[len(doneTodos)-1] == doneTodos[len(doneTodos)-3] {
if utils.LastDoneTodoWasRescheduled(doneTodos, todos) {
// Command was rescheduled, no need to display it
return nil
}
+34
View File
@@ -68,6 +68,40 @@ func findTodo(todos []todo.Todo, todoToFind Todo) (int, bool) {
return idx, ok
}
// LastDoneTodoWasRescheduled tells whether git put the last command of
// rebase-merge/done back into git-rebase-todo, given the parsed contents of
// these two files. In certain cases, git reschedules commands that failed. One
// example is if a patch would overwrite an untracked file; another one is an
// "exec" that failed.
func LastDoneTodoWasRescheduled(doneTodos []todo.Todo, todos []todo.Todo) bool {
// If the last command of the "done" file is the same as the first command
// of "git-rebase-todo", the command was rescheduled.
if len(doneTodos) > 0 && len(todos) > 0 && doneTodos[len(doneTodos)-1] == todos[0] {
return true
}
// Older versions of git have a bug whereby, if a command is rescheduled,
// the last successful command is appended to the "done" file again. To
// detect this, we need to compare the second-to-last done entry against the
// first todo entry, and also compare the last done entry against the
// last-but-two done entry; this latter check is needed for the following
// case:
// pick A
// exec make test
// pick B
// exec make test
// If pick B fails with conflicts, then the "done" file contains
// pick A
// exec make test
// pick B
// and git-rebase-todo contains
// exec make test
// Without the last condition we would erroneously treat this as the exec
// command being rescheduled.
return len(doneTodos) >= 3 && len(todos) > 0 && doneTodos[len(doneTodos)-2] == todos[0] &&
doneTodos[len(doneTodos)-1] == doneTodos[len(doneTodos)-3]
}
func ReadRebaseTodoFile(fileName string, commentChar byte) ([]todo.Todo, error) {
f, err := os.Open(fileName)
if err != nil {