git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v3 01/27] rebase -i: allow replaying commits with empty log messages

From
Fabian Ruch <bafain@gmail.com>
Date
Aug 18, 2014, 21:22 UTC
Message-ID
<ea58c1b83349b8bc4c2a0abf31de53a54f651299.1408396036.git.bafain@gmail.com>
In-Reply-To
<cover.1408396036.git.bafain@gmail.com>

git-rebase--interactive handles empty log messages inconsistently between enabled and disabled fast-forwards. By default, commits with empty log messages are rebased successfully like in non-interactive mode. In contrast, the `--no-ff` option aborts the replay of such commits.

In line with not verifying rebased commits and behaving like git-rebase for `pick` lines, use the `--allow-empty-message` option to replay commits. Root commits are replayed by recreating them in `do_pick` using git-commit and all other commits are replayed using git-cherry-pick in `pick_one`. Apply the option, understood by both git-commit and git-cherry-pick, at the respective sites.

In case of `reword` and `squash`, continue to abort the rebase if the _resulting_ commit would have no commit message. The rationale behind this default is that patches and their log messages should be verified at least once. For unchanged commits this is assumed to have happened according to the author's standards when she created the commits for the first time. While the empty log message can always be kept in place by editing and resuming the aborted rebase, a debatable alternative could be to teach git-rebase--interactive the option `--allow-empty-message` for disabling complaints about empty log messages even in changed commits.

The `fixup` case is different again because it throws away the second commit's log message and uses the first log message for the changed commit. Do not abort the rebase if that message is empty either since it is assumed to have been verified already.

The remaining to-do list command `edit` is handled just like `pick` for this matter, because git-rebase--interactive replays the named commit without changes before the rebase is interrupted and the user can make her changes to the replayed commit.

Add tests. In particular, design the `squash`-specific test case such that it involves interim commits and `fixup` steps. Interim commits should not trigger failures themselves and `fixup` steps should not let git-rebase--interactive forget that it is still dealing with a `squash` result.

Signed-off-by: Fabian Ruch <bafain@gmail.com>
---
 git-rebase--interactive.sh    | 10 ++++++----
 t/t3404-rebase-interactive.sh | 38 ++++++++++++++++++++++++++++++++++++++
 t/t3412-rebase-root.sh        | 16 ++++++++++++++++
 3 files changed, 60 insertions(+), 4 deletions(-)
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index b64dd28..3222bf6 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -249,7 +249,7 @@ pick_one () {
 
 	test -d "$rewritten" &&
 		pick_one_preserving_merges "$@" && return
-	output eval git cherry-pick \
+	output eval git cherry-pick --allow-empty-message \
 			${gpg_sign_opt:+$(git rev-parse --sq-quote "$gpg_sign_opt")} \
 			"$strategy_args" $empty_args $ff "$@"
 }
@@ -363,7 +363,7 @@ pick_one_preserving_merges () {
 			echo "$sha1 $(git rev-parse HEAD^0)" >> "$rewritten_list"
 			;;
 		*)
-			output eval git cherry-pick \
+			output eval git cherry-pick --allow-empty-message \
 				${gpg_sign_opt:+$(git rev-parse --sq-quote "$gpg_sign_opt")} \
 				"$strategy_args" "$@" ||
 				die_with_patch $sha1 "Could not pick $sha1"
@@ -549,7 +549,8 @@ do_next () {
 		squash|s|fixup|f)
 			# This is an intermediate commit; its message will only be
 			# used in case of trouble.  So use the long version:
-			do_with_author output git commit --amend --no-verify -F "$squash_msg" \
+			do_with_author output git commit --allow-empty-message \
+				--amend --no-verify -F "$squash_msg" \
 				${gpg_sign_opt:+"$gpg_sign_opt"} ||
 				die_failed_squash $sha1 "$rest"
 			;;
@@ -557,7 +558,8 @@ do_next () {
 			# This is the final command of this squash/fixup group
 			if test -f "$fixup_msg"
 			then
-				do_with_author git commit --amend --no-verify -F "$fixup_msg" \
+				do_with_author git commit --allow-empty-message \
+					--amend --no-verify -F "$fixup_msg" \
 					${gpg_sign_opt:+"$gpg_sign_opt"} ||
 					die_failed_squash $sha1 "$rest"
 			else
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index 8197ed2..9c71835 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -1039,4 +1039,42 @@ test_expect_success 'short SHA-1 collide' '
 	)
 '
 
+test_expect_success 'setup commits with empty commit log messages' '
+	git checkout -b empty-log-messages master &&
+	test_commit no-msg-commit-1 &&
+	git commit --amend --allow-empty-message -F - </dev/null &&
+	test_commit no-msg-commit-2 &&
+	git commit --amend --allow-empty-message -F - </dev/null &&
+	test_commit no-msg-commit-3 &&
+	git commit --amend --allow-empty-message -F - </dev/null
+'
+
+test_expect_success 'rebase commits with empty commit log messages' '
+	git checkout -b rebase-empty-log-messages empty-log-messages &&
+	set_fake_editor &&
+	test_expect_code 0 env FAKE_LINES="1" git rebase -i master &&
+	test_expect_code 0 env FAKE_LINES="1" git rebase -i --no-ff master
+'
+
+test_expect_success 'reword commits with empty commit log messages' '
+	git checkout -b reword-empty-log-messages empty-log-messages &&
+	test_when_finished reset_rebase &&
+	set_fake_editor &&
+	test_must_fail env FAKE_LINES="reword 1" git rebase -i master
+'
+
+test_expect_success 'squash commits with empty commit log messages' '
+	git checkout -b squash-empty-log-messages empty-log-messages &&
+	set_fake_editor &&
+	test_must_fail env FAKE_LINES="1 squash 2 fixup 3" git rebase -i master &&
+	git commit --allow-empty-message --amend &&
+	git rebase --continue
+'
+
+test_expect_success 'fixup commits with empty commit log messages' '
+	git checkout -b fixup-empty-log-messages empty-log-messages &&
+	set_fake_editor &&
+	env FAKE_LINES="1 fixup 2" git rebase -i master
+'
+
 test_done
diff --git a/t/t3412-rebase-root.sh b/t/t3412-rebase-root.sh
index 0b52105..7add7a1 100755
--- a/t/t3412-rebase-root.sh
+++ b/t/t3412-rebase-root.sh
@@ -278,4 +278,20 @@ test_expect_success 'rebase -i -p --root with conflict (second part)' '
 	test_cmp expect-conflict-p out
 '
 
+test_expect_success 'rebase --root root with empty log message' '
+	git checkout --orphan empty-log-messages-root master &&
+	test_commit no-msg-root-commit &&
+	git commit --amend --allow-empty-message -F - </dev/null &&
+	test_expect_code 0 git rebase --root &&
+	test_expect_code 0 git rebase --root --no-ff
+'
+
+test_expect_success 'rebase --root commits with empty log messages' '
+	git checkout -b empty-log-messages master &&
+	test_commit no-msg-commit &&
+	git commit --amend --allow-empty-message -F - </dev/null &&
+	test_expect_code 0 git rebase --root &&
+	test_expect_code 0 git rebase --root --no-ff
+'
+
 test_done
-- 
2.0.1
Previous: Fabian RuchNext: Fabian Ruch
Message 122 of 148 in “rebase -i: Implement `reword` and `squash` in terms of `do_pick`”
  1. 0/7 rebase -i: Implement `reword` and `squash` in terms of `do_pick`Fabian Ruch, Jun 19, 2014
  2. 00/19 Enable options --signoff, --reset-author for pick, rewordFabian Ruch, Jul 2, 2014
  3. 01/19 rebase -i: Failed reword prints redundant error messageFabian Ruch, Jul 2, 2014
  4. Junio C HamanoJul 8, 2014
  5. Andrew WongJul 10, 2014
  6. Fabian RuchJul 10, 2014
  7. Andrew WongJul 10, 2014
  8. 02/19 rebase -i: reword complains about empty commit despite --keep-emptyFabian Ruch, Jul 2, 2014
  9. Junio C HamanoJul 8, 2014
  10. Fabian RuchJul 9, 2014
  11. 03/19 rebase -i: reword executes pre-commit hook on interim commitFabian Ruch, Jul 2, 2014
  12. Junio C HamanoJul 8, 2014
  13. Fabian RuchJul 13, 2014
  14. 04/19 rebase -i: Teach do_pick the option --editFabian Ruch, Jul 2, 2014
  15. 05/19 rebase -i: Implement reword in terms of do_pickFabian Ruch, Jul 2, 2014
  16. Matthieu MoyAug 4, 2014
  17. Fabian RuchAug 4, 2014
  18. 06/19 rebase -i: Stop on root commits with empty log messagesFabian Ruch, Jul 2, 2014
  19. Junio C HamanoJul 8, 2014
  20. Fabian RuchJul 10, 2014
  21. Junio C HamanoJul 10, 2014
  22. Junio C HamanoJul 10, 2014
  23. 07/19 rebase -i: The replay of root commits is not shown with --verboseFabian Ruch, Jul 2, 2014
  24. Junio C HamanoJul 8, 2014
  25. Fabian RuchJul 11, 2014
  26. Chris WebbJul 15, 2014
  27. 08/19 rebase -i: Root commits are replayed with an unnecessary optionFabian Ruch, Jul 2, 2014
  28. Junio C HamanoJul 8, 2014
  29. Fabian RuchJul 18, 2014
  30. Junio C HamanoJul 18, 2014
  31. Fabian RuchJul 19, 2014
  32. 09/19 rebase -i: Commit only once when rewriting picksFabian Ruch, Jul 2, 2014
  33. 10/19 rebase -i: Do not die in do_pickFabian Ruch, Jul 2, 2014
  34. 11/19 rebase -i: Teach do_pick the option --amendFabian Ruch, Jul 2, 2014
  35. 12/19 rebase -i: Teach do_pick the option --fileFabian Ruch, Jul 2, 2014
  36. 13/19 rebase -i: Prepare for squash in terms of do_pick --amendFabian Ruch, Jul 2, 2014
  37. 14/19 rebase -i: Implement squash in terms of do_pickFabian Ruch, Jul 2, 2014
  38. 15/19 rebase -i: Explicitly distinguish replay commands and exec tasksFabian Ruch, Jul 2, 2014
  39. Junio C HamanoJul 10, 2014
  40. 16/19 rebase -i: Parse to-do list command line optionsFabian Ruch, Jul 2, 2014
  41. 17/19 rebase -i: Teach do_pick the option --reset-authorFabian Ruch, Jul 2, 2014
  42. 18/19 rebase -i: Teach do_pick the option --signoffFabian Ruch, Jul 2, 2014
  43. 19/19 rebase -i: Enable options --signoff, --reset-author for pick, rewordFabian Ruch, Jul 2, 2014
  44. Michael HaggertyJul 3, 2014
  45. Junio C HamanoJul 8, 2014
  46. Fabian RuchJul 9, 2014
  47. Thomas RastJul 18, 2014
  48. 00/19 Enable options --signoff, --reset-author for pick, rewordFabian Ruch, Jul 28, 2014
  49. 01/19 rebase -i: failed reword prints redundant error messageFabian Ruch, Jul 28, 2014
  50. 02/19 rebase -i: allow rewording an empty commit without complaintsFabian Ruch, Jul 28, 2014
  51. 03/19 rebase -i: reword executes pre-commit hook on interim commitFabian Ruch, Jul 28, 2014
  52. Jeff KingAug 1, 2014
  53. Fabian RuchAug 4, 2014
  54. Jeff KingAug 6, 2014
  55. 04/19 rebase -i: teach do_pick the option --editFabian Ruch, Jul 28, 2014
  56. 05/19 rebase -i: implement reword in terms of do_pickFabian Ruch, Jul 28, 2014
  57. 06/19 rebase -i: allow replaying commits with empty log messagesFabian Ruch, Jul 28, 2014
  58. 07/19 rebase -i: log the replay of root commitsFabian Ruch, Jul 28, 2014
  59. Jeff KingAug 2, 2014
  60. Fabian RuchAug 4, 2014
  61. Jeff KingAug 6, 2014
  62. 08/19 rebase -i: root commits are replayed with an unnecessary optionFabian Ruch, Jul 28, 2014
  63. Jeff KingAug 2, 2014
  64. Fabian RuchAug 4, 2014
  65. 09/19 rebase -i: commit only once when rewriting picksFabian Ruch, Jul 28, 2014
  66. Jeff KingAug 2, 2014
  67. Fabian RuchAug 7, 2014
  68. 10/19 rebase -i: do not die in do_pickFabian Ruch, Jul 28, 2014
  69. 11/19 rebase -i: teach do_pick the option --amendFabian Ruch, Jul 28, 2014
  70. 12/19 rebase -i: teach do_pick the option --fileFabian Ruch, Jul 28, 2014
  71. 13/19 rebase -i: prepare for squash in terms of do_pick --amendFabian Ruch, Jul 28, 2014
  72. 14/19 rebase -i: implement squash in terms of do_pickFabian Ruch, Jul 28, 2014
  73. 15/19 rebase -i: explicitly distinguish replay commands and exec tasksFabian Ruch, Jul 28, 2014
  74. 16/19 rebase -i: parse to-do list command line optionsFabian Ruch, Jul 28, 2014
  75. 17/19 rebase -i: teach do_pick the option --reset-authorFabian Ruch, Jul 28, 2014
  76. 18/19 rebase -i: teach do_pick the option --signoffFabian Ruch, Jul 28, 2014
  77. 19/19 rebase -i: enable options --signoff, --reset-author for pick, rewordFabian Ruch, Jul 28, 2014
  78. Jeff KingAug 2, 2014
  79. Fabian RuchAug 4, 2014
  80. 00/23 Enable options --signoff, --reset-author for pick, rewordFabian Ruch, Aug 6, 2014
  81. 01/23 rebase -i: allow replaying commits with empty log messagesFabian Ruch, Aug 6, 2014
  82. 02/23 rebase -i: allow squashing empty commits without complaintsFabian Ruch, Aug 6, 2014
  83. Peter KreftingAug 7, 2014
  84. Eric SunshineAug 7, 2014
  85. Fabian RuchAug 11, 2014
  86. Phil HordAug 13, 2014
  87. 03/23 rebase -i: allow rewording empty commits without complaintsFabian Ruch, Aug 6, 2014
  88. 04/23 rebase -i: hide interactive command messages in verbose modeFabian Ruch, Aug 6, 2014
  89. Thomas RastAug 8, 2014
  90. Fabian RuchAug 11, 2014
  91. Thomas RastAug 11, 2014
  92. 05/23 rebase -i: failed reword prints redundant error messageFabian Ruch, Aug 6, 2014
  93. 06/23 commit: allow disabling pre-commit and commit-msg separatelyFabian Ruch, Aug 6, 2014
  94. 07/23 rebase -i: squash skips commit-msg hookFabian Ruch, Aug 6, 2014
  95. 08/23 rebase -i: reword executes pre-commit hook on interim commitFabian Ruch, Aug 6, 2014
  96. Thomas RastAug 8, 2014
  97. Fabian RuchAug 11, 2014
  98. Thomas RastAug 11, 2014
  99. 09/23 rebase -i: teach do_pick the option --editFabian Ruch, Aug 6, 2014
  100. 10/23 rebase -i: implement reword in terms of do_pickFabian Ruch, Aug 6, 2014
  101. 11/23 rebase -i: log the replay of root commitsFabian Ruch, Aug 6, 2014
  102. 12/23 rebase -i: root commits are replayed with an unnecessary optionFabian Ruch, Aug 6, 2014
  103. 13/23 rebase -i: commit only once when rewriting picksFabian Ruch, Aug 6, 2014
  104. 14/23 rebase -i: do not die in do_pickFabian Ruch, Aug 6, 2014
  105. 15/23 rebase -i: teach do_pick the option --amendFabian Ruch, Aug 6, 2014
  106. 16/23 rebase -i: teach do_pick the option --fileFabian Ruch, Aug 6, 2014
  107. 17/23 rebase -i: prepare for squash in terms of do_pick --amendFabian Ruch, Aug 6, 2014
  108. 18/23 rebase -i: implement squash in terms of do_pickFabian Ruch, Aug 6, 2014
  109. 19/23 rebase -i: explicitly distinguish replay commands and exec tasksFabian Ruch, Aug 6, 2014
  110. 20/23 rebase -i: parse to-do list command line optionsFabian Ruch, Aug 6, 2014
  111. Thomas RastAug 8, 2014
  112. Fabian RuchAug 11, 2014
  113. 21/23 rebase -i: teach do_pick the option --reset-authorFabian Ruch, Aug 6, 2014
  114. 22/23 rebase -i: teach do_pick the option --signoffFabian Ruch, Aug 6, 2014
  115. 23/23 rebase -i: enable options --signoff, --reset-author for pick, rewordFabian Ruch, Aug 6, 2014
  116. Thomas RastAug 8, 2014
  117. Fabian RuchAug 12, 2014
  118. Michael HaggertyAug 13, 2014
  119. Fabian RuchAug 14, 2014
  120. Fabian RuchSep 21, 2014
  121. 00/27 Enable options --signoff, --reset-author for pick, reword, editFabian Ruch, Aug 18, 2014
  122. 01/27 rebase -i: allow replaying commits with empty log messagesFabian Ruch, Aug 18, 2014
  123. 02/27 rebase -i: allow squashing empty commits without complaintsFabian Ruch, Aug 18, 2014
  124. 03/27 rebase -i: allow rewording empty commits without complaintsFabian Ruch, Aug 18, 2014
  125. 04/27 fake_editor: leave standard output unchangedFabian Ruch, Aug 18, 2014
  126. 05/27 rebase -i: hide interactive command messages in verbose modeFabian Ruch, Aug 18, 2014
  127. 06/27 rebase -i: discard redundant message when rewording failsFabian Ruch, Aug 18, 2014
  128. 07/27 commit: allow disabling pre-commit and commit-msg separatelyFabian Ruch, Aug 18, 2014
  129. 08/27 rebase -i: verify squash messages using commit-msgFabian Ruch, Aug 18, 2014
  130. 09/27 rebase -i: do not verify reworded patches using pre-commitFabian Ruch, Aug 18, 2014
  131. 10/27 rebase -i: teach do_pick the option --editFabian Ruch, Aug 18, 2014
  132. 11/27 rebase -i: implement reword in terms of do_pickFabian Ruch, Aug 18, 2014
  133. 12/27 rebase -i: log the replay of root commitsFabian Ruch, Aug 18, 2014
  134. 13/27 rebase -i: do not use -C when --no-edit is sufficientFabian Ruch, Aug 18, 2014
  135. 14/27 rebase -i: commit only once when rewriting picksFabian Ruch, Aug 18, 2014
  136. 15/27 rebase -i: do not die in do_pickFabian Ruch, Aug 18, 2014
  137. 16/27 rebase -i: teach do_pick the option --amendFabian Ruch, Aug 18, 2014
  138. 17/27 rebase -i: teach do_pick the option --fileFabian Ruch, Aug 18, 2014
  139. 18/27 rebase -i: remove no-op do_with_author git commit --amendFabian Ruch, Aug 18, 2014
  140. 19/27 rebase -i: prepare for squash in terms of do_pick --amendFabian Ruch, Aug 18, 2014
  141. 20/27 rebase -i: implement squash in terms of do_pickFabian Ruch, Aug 18, 2014
  142. 21/27 rebase -i: explicitly distinguish replay commands and exec tasksFabian Ruch, Aug 18, 2014
  143. 22/27 rebase -i: parse to-do list command line optionsFabian Ruch, Aug 18, 2014
  144. 23/27 rebase -i: teach do_pick the option --reset-authorFabian Ruch, Aug 18, 2014
  145. 24/27 rebase -i: teach do_pick the option --signoffFabian Ruch, Aug 18, 2014
  146. 25/27 rebase -i: do not overwrite user author informationFabian Ruch, Aug 18, 2014
  147. 26/27 rebase -i: refuse to commit when resuming with updated headFabian Ruch, Aug 18, 2014
  148. 27/27 rebase -i: enable --signoff, --reset-author for pick, reword, editFabian Ruch, Aug 18, 2014

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.