git/list[1] front-page[2] threads[3] people[4] search[5] about
wed 2026-10-07 17:25 UTC

[PATCH v2 10/10] sequencer: do not record dropped commits as rewritten

From
PWPhillip Wood <phillip.wood123@gmail.com>
Date
Jul 13, 2026, 13:17 UTC
Message-ID
<c89234dd949f59ce150f0fb5d7442e1f46e3fef3.1783948637.git.phillip.wood@dunelm.org.uk>
In-Reply-To
<cover.1783948637.git.phillip.wood@dunelm.org.uk>
From: Phillip Wood <phillip.wood@dunelm.org.uk>

If a commit gets dropped because its changes are already upstream then we should not record it as rewritten. As well as confusing any post-rewrite hooks this means we end up copying the notes from the dropped commit to the commit that was picked immediately before the one that was dropped.

While we do not want to record the dropped commit is rewritten, if it is the final commit in a chain of fixups then we need to flush the list of rewritten commits. The behavior of an "edit" command where the commit is dropped is changed so that "rebase --continue" will not amend the previous pick. However, as the code comment notes it will still be erroneously recorded as rewritten when the rebase continues. That will need to be addressed separately along with not recording skipped commits as rewritten.

The initialization of "drop_commit" is moved to ensure it is initialized when rewording a fast-forwarded commit.

Reported-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
Tested-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
---
 sequencer.c                  | 24 +++++++++++++++++++-----
 t/t3400-rebase.sh            | 12 ++++++++++++
 t/t5407-post-rewrite-hook.sh | 23 +++++++++++++++++++++++
 3 files changed, 54 insertions(+), 5 deletions(-)
diff --git a/sequencer.c b/sequencer.c
index 4b89349251b..7bc885085f9 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -2264,6 +2264,7 @@ enum pick_result {
 	PICK_RESULT_ERROR = -1,
 	PICK_RESULT_OK,
 	PICK_RESULT_CONFLICTS,
+	PICK_RESULT_DROPPED,
 };
 
 static enum pick_result do_pick_commit(struct repository *r,
@@ -2279,7 +2280,7 @@ static enum pick_result do_pick_commit(struct repository *r,
 	const char *base_label, *next_label, *reflog_action;
 	char *author = NULL;
 	struct commit_message msg = { NULL, NULL, NULL, NULL };
-	int res, unborn = 0, reword = 0, allow, drop_commit;
+	int res, unborn = 0, reword = 0, allow, drop_commit = 0;
 	enum todo_command command = item->command;
 	struct commit *commit = item->commit;
 
@@ -2509,7 +2510,6 @@ static enum pick_result do_pick_commit(struct repository *r,
 		goto leave;
 	}
 
-	drop_commit = 0;
 	allow = allow_empty(r, opts, commit);
 	if (allow < 0) {
 		res = allow;
@@ -2574,6 +2574,8 @@ static enum pick_result do_pick_commit(struct repository *r,
 		return PICK_RESULT_ERROR;
 	else if (res > 0)
 		return PICK_RESULT_CONFLICTS;
+	else if (drop_commit)
+		return PICK_RESULT_DROPPED;
 	else
 		return PICK_RESULT_OK;
 }
@@ -4994,18 +4996,30 @@ static int pick_one_commit(struct repository *r,
 	} else if (item->command == TODO_EDIT) {
 		struct commit *commit = item->commit;
 		int res = pick_res == PICK_RESULT_CONFLICTS;
+		int to_amend = pick_res != PICK_RESULT_CONFLICTS &&
+				pick_res != PICK_RESULT_DROPPED;
 
-		if (pick_res == PICK_RESULT_OK) {
+		/*
+		 * NEEDSWORK: Do not record the commit as rewritten when
+		 * continuing if it was dropped. Does it even make sense
+		 * to stop if the commit was dropped?
+		 */
+		if (pick_res == PICK_RESULT_OK ||
+		    pick_res == PICK_RESULT_DROPPED) {
 			if (!opts->verbose)
 				term_clear_line();
 			fprintf(stderr, _("Stopped at %s...  %.*s\n"),
 				short_commit_name(r, commit), item->arg_len, arg);
 		}
-		return error_with_patch(r, commit,
-					arg, item->arg_len, opts, res, !res);
+		return error_with_patch(r, commit, arg, item->arg_len, opts,
+					res, to_amend);
 	} else if (pick_res == PICK_RESULT_OK) {
 		record_in_rewritten(&item->commit->object.oid,
 				    peek_command(todo_list, 1));
+		return 0;
+	} else if (pick_res == PICK_RESULT_DROPPED) {
+		if (is_final_fixup(todo_list))
+			flush_rewritten_pending();
 		return 0;
 	} else if (pick_res == PICK_RESULT_CONFLICTS &&
 		   is_fixup(item->command)) {
diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh
index f0e7fcf649a..1d09886ea35 100755
--- a/t/t3400-rebase.sh
+++ b/t/t3400-rebase.sh
@@ -274,6 +274,18 @@ test_expect_success 'rebase --apply can copy notes' '
 	git reset --hard n3 &&
 	git rebase --apply --onto n1 n2 &&
 	test "a note" = "$(git notes show HEAD)"
+'
+
+test_expect_success 'rebase drops notes of dropped commits' '
+	git checkout n1 &&
+	echo n3 >n3.t &&
+	echo n4 >n4.t &&
+	git add n3.t n4.t &&
+	git commit -m n34 &&
+	git rebase HEAD n3 &&
+	test_commit_message HEAD -m n2 &&
+	test_must_fail git notes list HEAD >actual &&
+	test_must_be_empty actual
 '
 
 test_expect_success 'rebase commit with an ancient timestamp' '
diff --git a/t/t5407-post-rewrite-hook.sh b/t/t5407-post-rewrite-hook.sh
index ad7f8c6f002..51991956d1d 100755
--- a/t/t5407-post-rewrite-hook.sh
+++ b/t/t5407-post-rewrite-hook.sh
@@ -306,6 +306,29 @@ test_expect_success 'git rebase -i (exec)' '
 	cat >expected.data <<-EOF &&
 	$(git rev-parse C) $(git rev-parse HEAD^)
 	$(git rev-parse D) $(git rev-parse HEAD)
+	EOF
+	verify_hook_input
+'
+
+test_expect_success 'rebase with commits that become empty' '
+	cat >todo <<-\EOF &&
+	pick H
+	pick E
+	fixup I
+	fixup H
+	pick G
+	pick I
+	EOF
+	(
+		set_replace_editor todo &&
+		git rebase -i --empty=drop A A
+	) &&
+	echo rebase >expected.args &&
+	cat >expected.data <<-EOF &&
+	$(git rev-parse H) $(git rev-parse HEAD~2)
+	$(git rev-parse E) $(git rev-parse HEAD~1)
+	$(git rev-parse I) $(git rev-parse HEAD~1)
+	$(git rev-parse G) $(git rev-parse HEAD)
 	EOF
 	verify_hook_input
 '
-- 
2.54.0.200.gfd8d68259e3
Previous: Phillip WoodNext: Oswald Buddenhagen
Message 40 of 67 in “sequencer: Skip copying notes for commits that disappear during rebase”
  1. sequencer: Skip copying notes for commits that disappear during rebaseUwe Kleine-König, Jun 16, 2026
  2. Junio C HamanoJun 17, 2026
  3. Uwe Kleine-KönigJun 17, 2026
  4. Phillip WoodJun 19, 2026
  5. Uwe Kleine-KönigJun 19, 2026
  6. 00/11 sequencer: do not record dropped commits as rewrittenPhillip Wood, Jun 30, 2026
  7. 01/11 t3400: restore coverage for note copying with apply backendPhillip Wood, Jun 30, 2026
  8. 02/11 sequencer: move definition of is_final_fixup()Phillip Wood, Jun 30, 2026
  9. 03/11 sequencer: be more careful with external mergePhillip Wood, Jun 30, 2026
  10. 04/11 sequencer: never reschedule on failed commitPhillip Wood, Jun 30, 2026
  11. 05/11 sequencer: remove unnecessary "or" in pick_one_commit()Phillip Wood, Jun 30, 2026
  12. 06/11 sequencer: simplify handing of fixup with conflictsPhillip Wood, Jun 30, 2026
  13. 07/11 sequencer: remove unnecessary condition in pick_one_commit()Phillip Wood, Jun 30, 2026
  14. 08/11 sequencer: simplify pick_one_commit()Phillip Wood, Jun 30, 2026
  15. 09/11 sequencer: return early from pick_one_commit() on successPhillip Wood, Jun 30, 2026
  16. 11/11 sequencer: do not record dropped commits as rewrittenPhillip Wood, Jun 30, 2026
  17. 10/11 sequencer: use an enum to represent result of picking a commitPhillip Wood, Jun 30, 2026
  18. Junio C HamanoJun 30, 2026
  19. Uwe Kleine-KönigJul 1, 2026
  20. Uwe Kleine-KönigJul 1, 2026
  21. Phillip WoodJul 1, 2026
  22. Phillip WoodJul 1, 2026
  23. Phillip WoodJul 1, 2026
  24. Oswald BuddenhagenJul 6, 2026
  25. Oswald BuddenhagenJul 6, 2026
  26. Oswald BuddenhagenJul 6, 2026
  27. Phillip WoodJul 6, 2026
  28. Phillip WoodJul 6, 2026
  29. Junio C HamanoJul 13, 2026
  30. 00/10 sequencer: do not record dropped commits as rewrittenPhillip Wood, Jul 13, 2026
  31. 01/10 t3400: restore coverage for note copying with apply backendPhillip Wood, Jul 13, 2026
  32. 02/10 sequencer: move definition of is_final_fixup()Phillip Wood, Jul 13, 2026
  33. 03/10 sequencer: be more careful with external mergePhillip Wood, Jul 13, 2026
  34. 04/10 sequencer: never reschedule on failed commitPhillip Wood, Jul 13, 2026
  35. 05/10 sequencer: remove unnecessary "or" in pick_one_commit()Phillip Wood, Jul 13, 2026
  36. 06/10 sequencer: simplify handing of fixup with conflictsPhillip Wood, Jul 13, 2026
  37. 07/10 sequencer: remove unnecessary condition in pick_one_commit()Phillip Wood, Jul 13, 2026
  38. 08/10 sequencer: simplify pick_one_commit()Phillip Wood, Jul 13, 2026
  39. 09/10 sequencer: use an enum to represent result of picking a commitPhillip Wood, Jul 13, 2026
  40. 10/10 sequencer: do not record dropped commits as rewrittenPhillip Wood, Jul 13, 2026
  41. Oswald BuddenhagenJul 13, 2026
  42. Oswald BuddenhagenJul 13, 2026
  43. Oswald BuddenhagenJul 13, 2026
  44. Junio C HamanoJul 13, 2026
  45. Andrei RybakJul 14, 2026
  46. Phillip WoodJul 15, 2026
  47. Phillip WoodJul 15, 2026
  48. Phillip WoodJul 15, 2026
  49. Phillip WoodJul 15, 2026
  50. 1/9 t3400: restore coverage for note copying with apply backendPhillip Wood, Jul 15, 2026
  51. 0/9 sequencer: do not record dropped commits as rewrittenPhillip Wood, Jul 15, 2026
  52. 3/9 sequencer: never reschedule on failed commitPhillip Wood, Jul 15, 2026
  53. 2/9 sequencer: be more careful with external mergePhillip Wood, Jul 15, 2026
  54. 4/9 sequencer: remove unnecessary "or" in pick_one_commit()Phillip Wood, Jul 15, 2026
  55. 5/9 sequencer: simplify handling of fixup with conflictsPhillip Wood, Jul 15, 2026
  56. 6/9 sequencer: remove unnecessary condition in pick_one_commit()Phillip Wood, Jul 15, 2026
  57. 7/9 sequencer: simplify pick_one_commit()Phillip Wood, Jul 15, 2026
  58. 8/9 sequencer: use an enum to represent result of picking a commitPhillip Wood, Jul 15, 2026
  59. 9/9 sequencer: do not record dropped commits as rewrittenPhillip Wood, Jul 15, 2026
  60. Junio C HamanoJul 15, 2026
  61. Uwe Kleine-KönigJul 18, 2026
  62. Phillip WoodJul 18, 2026
  63. Junio C HamanoJul 19, 2026
  64. Oswald BuddenhagenJul 20, 2026
  65. Junio C HamanoJul 20, 2026
  66. gerrit code review once more (was: Re: [PATCH v3 0/9] sequencer: do not record dropped commits as) rewrittenOswald Buddenhagen, Jul 20, 2026
  67. Phillip WoodJul 22, 2026

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.