sequencer: avoid dropping fixup commit that targets self via commit-ish

Commit 68d5d03bc4 (rebase: teach --autosquash to match on sha1 in
addition to message, 2010-11-04) taught autosquash to recognize
subjects like "fixup! 7a235b" where 7a235b is an OID-prefix. It
actually did more than advertised: 7a235b can be an arbitrary
commit-ish (as long as it's not trailed by spaces).

Accidental(?) use of this secret feature revealed a bug where we
would silently drop a fixup commit. The bug can also be triggered
when using an OID-prefix but that's unlikely in practice.

Let the commit with subject "fixup! main" be the tip of the "main"
branch. When computing the fixup target for this commit, we find
the commit itself. This is wrong because, by definition, a fixup
target must be an earlier commit in the todo list. We wrongly find
the current commit because we added it to the todo list prematurely.
Avoid these fixup-cycles by only adding the current commit to the
todo list after we have finished looking for the fixup target.

Reported-by: Erik Cervin Edin <erik@cervined.in>
Signed-off-by: Johannes Altmanninger <aclopte@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Johannes Altmanninger 2022-09-24 17:29:04 -05:00 committed by Junio C Hamano
parent fd59c5bdee
commit 3e367a5f2f
2 changed files with 15 additions and 2 deletions

View file

@ -5774,8 +5774,6 @@ int todo_list_rearrange_squash(struct todo_list *todo_list)
return error(_("the script was already rearranged."));
}
*commit_todo_item_at(&commit_todo, item->commit) = item;
parse_commit(item->commit);
commit_buffer = logmsg_reencode(item->commit, NULL, "UTF-8");
find_commit_subject(commit_buffer, &subject);
@ -5842,6 +5840,8 @@ int todo_list_rearrange_squash(struct todo_list *todo_list)
strhash(entry->subject));
hashmap_put(&subject2item, &entry->entry);
}
*commit_todo_item_at(&commit_todo, item->commit) = item;
}
if (rearranged) {

View file

@ -232,6 +232,19 @@ test_expect_success 'auto squash that matches longer sha1' '
test_line_count = 1 actual
'
test_expect_success 'auto squash of fixup commit that matches branch name which points back to fixup commit' '
git reset --hard base &&
git commit --allow-empty -m "fixup! self-cycle" &&
git branch self-cycle &&
GIT_SEQUENCE_EDITOR="cat >tmp" git rebase --autosquash -i HEAD^^ &&
sed -ne "/^[^#]/{s/[0-9a-f]\{7,\}/HASH/g;p;}" tmp >actual &&
cat <<-EOF >expect &&
pick HASH second commit
pick HASH fixup! self-cycle # empty
EOF
test_cmp expect actual
'
test_auto_commit_flags () {
git reset --hard base &&
echo 1 >file1 &&