rebase -i: do leave commit message intact in fixup! chains

In 6e98de72c03 (sequencer (rebase -i): add support for the 'fixup' and 'squash' commands, 2017-01-02), this developer introduced a change of behavior by mistake: when encountering a `fixup!` commit (or multiple `fixup!` commits) without any `squash!` commit thrown in, the final `git commit` was invoked with `--cleanup=strip`. Prior to that commit, the commit command had been called without that `--cleanup` option. Since we explicitly read the original commit message from a file in that case, there is really no sense in forcing that clean-up. We actually need to actively suppress that clean-up lest a configured `commit.cleanup` may interfere with what we want to do: leave the commit message unchanged. Reported-by: Vojtěch Knyttl <vojtech@knyt.tl> Helped-by: Martin Ågren <martin.agren@gmail.com> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Johannes Schindelin committed Jan 28, 2021 at 16:16 UTC f7d42ceec5265f6dbcaeb527657521b7ec8ddc94
2 files changed +20 -1
sequencer.c
+12 -1
@@ -943,6 +943,7 @@ N_("you have staged changes in your working tree\n"
943 #define CLEANUP_MSG (1<<3)
944 #define VERIFY_MSG (1<<4)
945 #define CREATE_ROOT_COMMIT (1<<5)
946 +#define VERBATIM_MSG (1<<6)
947
948 static int run_command_silent_on_success(struct child_process *cmd)
949 {
@@ -979,6 +980,9 @@ static int run_git_commit(const char *defmsg,
980 {
981 struct child_process cmd = CHILD_PROCESS_INIT;
982
983 + if ((flags & CLEANUP_MSG) && (flags & VERBATIM_MSG))
984 + BUG("CLEANUP_MSG and VERBATIM_MSG are mutually exclusive");
985 +
986 cmd.git_cmd = 1;
987
988 if (is_rebase_i(opts) && read_env_script(&cmd.env_array)) {
@@ -1012,6 +1016,8 @@ static int run_git_commit(const char *defmsg,
1016 strvec_pushl(&cmd.args, "-C", "HEAD", NULL);
1017 if ((flags & CLEANUP_MSG))
1018 strvec_push(&cmd.args, "--cleanup=strip");
1019 + if ((flags & VERBATIM_MSG))
1020 + strvec_push(&cmd.args, "--cleanup=verbatim");
1021 if ((flags & EDIT_MSG))
1022 strvec_push(&cmd.args, "-e");
1023 else if (!(flags & CLEANUP_MSG) &&
@@ -1380,6 +1386,9 @@ static int try_to_commit(struct repository *r,
1386 enum commit_msg_cleanup_mode cleanup;
1387 int res = 0;
1388
1389 + if ((flags & CLEANUP_MSG) && (flags & VERBATIM_MSG))
1390 + BUG("CLEANUP_MSG and VERBATIM_MSG are mutually exclusive");
1391 +
1392 if (parse_head(r, &current_head))
1393 return -1;
1394
@@ -1454,6 +1463,8 @@ static int try_to_commit(struct repository *r,
1463
1464 if (flags & CLEANUP_MSG)
1465 cleanup = COMMIT_MSG_CLEANUP_ALL;
1466 + else if (flags & VERBATIM_MSG)
1467 + cleanup = COMMIT_MSG_CLEANUP_NONE;
1468 else if ((opts->signoff || opts->record_origin) &&
1469 !opts->explicit_cleanup)
1470 cleanup = COMMIT_MSG_CLEANUP_SPACE;
@@ -2002,7 +2013,7 @@ static int do_pick_commit(struct repository *r,
2013 if (!final_fixup)
2014 msg_file = rebase_path_squash_msg();
2015 else if (file_exists(rebase_path_fixup_msg())) {
2005 - flags |= CLEANUP_MSG;
2016 + flags |= VERBATIM_MSG;
2017 msg_file = rebase_path_fixup_msg();
2018 } else {
2019 const char *dest = git_path_squash_msg(r);
t/t3415-rebase-autosquash.sh
+8
@@ -440,4 +440,12 @@ test_expect_success 'fixup a fixup' '
440 test XZWY = $(git show | tr -cd W-Z)
441 '
442
443 +test_expect_success 'fixup does not clean up commit message' '
444 + oneline="#818" &&
445 + git commit --allow-empty -m "$oneline" &&
446 + git commit --fixup HEAD --allow-empty &&
447 + git -c commit.cleanup=strip rebase -ki --autosquash HEAD~2 &&
448 + test "$oneline" = "$(git show -s --format=%s)"
449 +'
450 +
451 test_done