{"thread":{"id":"49265","subject":"[PATCH 0/2] rebase --autosquash: handle manual \"final fixups\"","startedAt":"2018-08-31T23:45:04Z","lastAt":"2018-09-05T16:28:13Z","messageCount":8,"participants":["Johannes Schindelin via GitGitGadget","Junio C Hamano","Johannes Schindelin"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"357143","messageId":"pull.30.git.gitgitgadget@gmail.com","threadId":"49265","inReplyTo":null,"subject":"[PATCH 0/2] rebase --autosquash: handle manual \"final fixups\"","fromName":"Johannes Schindelin via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2018-08-31T23:45:01Z","receivedAt":"2018-08-31T23:45:04Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"'tis bug fix season! I admit, though, that this bug might be a bit too off\nthe trodden path to merit fast-tracking into v2.19.0.\n\nWhile pairing with Jameson Miller to rebase Git for Windows to v2.19.0-rc1,\nwe had to fix a couple of commits which had somehow lost their proper\nauthorship (probably due to long fixed bugs in the interactive rebase). We\ndid so by using empty squash! commits as reminders, so that we could\ninterrupt the rebase by deleting the squash message, amend the commit\nappropriately, and then continue.\n\nThis exposed an (admittedly obscure) bug in the interactive rebase: when the\nlast fixup or squash of a fixup/squash chain is aborted, and then the HEAD\ncommit is amended, the rebase would not forget about the fixup/squash chain.\nIt would hold onto the information about the current fixup count and the\nintermediate commit message. And upon processing another fixup/squash chain,\nthat information would be reused!\n\nThis patch pair first introduces the test case to confirm the breakage, and\nthen fixes it in the minimal way.\n\nJohannes Schindelin (2):\n  rebase -i --autosquash: demonstrate a problem skipping the last squash\n  rebase -i: be careful to wrap up fixup/squash chains\n\n sequencer.c                  | 17 ++++++++++++++---\n t/t3415-rebase-autosquash.sh | 19 +++++++++++++++++++\n 2 files changed, 33 insertions(+), 3 deletions(-)\n\n\nbase-commit: 2f743933341f276111103550fbf383a34dfcfd38\nPublished-As: https://github.com/gitgitgadget/git/releases/tags/pr-30%2Fdscho%2Frebase-abort-last-squash-v1\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-30/dscho/rebase-abort-last-squash-v1\nPull-Request: https://github.com/gitgitgadget/git/pull/30\n-- \ngitgitgadget\n"},{"id":"357144","messageId":"8753c4e5fba5bb9cc42fdf438f4a69e702261a15.1535759099.git.gitgitgadget@gmail.com","threadId":"49265","inReplyTo":"pull.30.git.gitgitgadget@gmail.com","subject":"[PATCH 1/2] rebase -i --autosquash: demonstrate a problem skipping the last squash","fromName":"Johannes Schindelin via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2018-08-31T23:45:02Z","receivedAt":"2018-08-31T23:45:09Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"From: Johannes Schindelin <johannes.schindelin@gmx.de>\n\nThe `git commit --squash` command can be used not only to amend commit\nmessages and changes, but also to record notes for an upcoming rebase.\n\nFor example, when the author information of a given commit is incorrect,\na user might call `git commit --allow-empty -m \"Fix author\" --squash\n<commit>`, to remind them to fix that during the rebase. When the editor\nwould pop up, the user would simply delete the commit message to abort\nthe rebase at this stage, fix the author information, and continue with\n`git rebase --skip`. (This is a real-world example from the rebase of\nGit for Windows onto v2.19.0-rc1.)\n\nHowever, there is a bug in `git rebase` that will cause the squash\nmessage *not* to be forgotten in this case. It will therefore be reused\nin the next fixup/squash chain (if any).\n\nThis patch adds a test case to demonstrate this breakage.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n t/t3415-rebase-autosquash.sh | 19 +++++++++++++++++++\n 1 file changed, 19 insertions(+)\n\ndiff --git a/t/t3415-rebase-autosquash.sh b/t/t3415-rebase-autosquash.sh\nindex e364c12622..7d5ea340b3 100755\n--- a/t/t3415-rebase-autosquash.sh\n+++ b/t/t3415-rebase-autosquash.sh\n@@ -330,4 +330,23 @@ test_expect_success 'wrapped original subject' '\n \ttest $base = $parent\n '\n \n+test_expect_failure 'abort last squash' '\n+\ttest_when_finished \"test_might_fail git rebase --abort\" &&\n+\ttest_when_finished \"git checkout master\" &&\n+\n+\tgit checkout -b some-squashes &&\n+\tgit commit --allow-empty -m first &&\n+\tgit commit --allow-empty --squash HEAD &&\n+\tgit commit --allow-empty -m second &&\n+\tgit commit --allow-empty --squash HEAD &&\n+\n+\ttest_must_fail git -c core.editor=\"grep -q ^pick\" \\\n+\t\trebase -ki --autosquash HEAD~4 &&\n+\t: do not finish the squash, but resolve it manually &&\n+\tgit commit --allow-empty --amend -m edited-first &&\n+\tgit rebase --skip &&\n+\tgit show >actual &&\n+\t! grep first actual\n+'\n+\n test_done\n-- \ngitgitgadget\n\n"},{"id":"357145","messageId":"0c9d0f75fc0dd28d55d4ed41d008182746fc86cd.1535759099.git.gitgitgadget@gmail.com","threadId":"49265","inReplyTo":"pull.30.git.gitgitgadget@gmail.com","subject":"[PATCH 2/2] rebase -i: be careful to wrap up fixup/squash chains","fromName":"Johannes Schindelin via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2018-08-31T23:45:04Z","receivedAt":"2018-08-31T23:45:09Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"From: Johannes Schindelin <johannes.schindelin@gmx.de>\n\nWhen an interactive rebase was stopped at the end of a fixup/squash\nchain, the user might have edited the commit manually before continuing\n(with either `git rebase --skip` or `git rebase --continue`, it does not\nreally matter which).\n\nWe need to be very careful to wrap up the fixup/squash chain also in\nthis scenario: otherwise the next fixup/squash chain would try to pick\nup where the previous one was left.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n sequencer.c                  | 17 ++++++++++++++---\n t/t3415-rebase-autosquash.sh |  2 +-\n 2 files changed, 15 insertions(+), 4 deletions(-)\n\ndiff --git a/sequencer.c b/sequencer.c\nindex 84bf598c3e..ac5c805c14 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -3578,9 +3578,20 @@ static int commit_staged_changes(struct replay_opts *opts,\n \t\t * the commit message and if there was a squash, let the user\n \t\t * edit it.\n \t\t */\n-\t\tif (is_clean && !oidcmp(&head, &to_amend) &&\n-\t\t    opts->current_fixup_count > 0 &&\n-\t\t    file_exists(rebase_path_stopped_sha())) {\n+\t\tif (!is_clean || !opts->current_fixup_count)\n+\t\t\t; /* this is not the final fixup */\n+\t\telse if (oidcmp(&head, &to_amend) ||\n+\t\t\t !file_exists(rebase_path_stopped_sha())) {\n+\t\t\t/* was a final fixup or squash done manually? */\n+\t\t\tif (!is_fixup(peek_command(todo_list, 0))) {\n+\t\t\t\tunlink(rebase_path_fixup_msg());\n+\t\t\t\tunlink(rebase_path_squash_msg());\n+\t\t\t\tunlink(rebase_path_current_fixups());\n+\t\t\t\tstrbuf_reset(&opts->current_fixups);\n+\t\t\t\topts->current_fixup_count = 0;\n+\t\t\t}\n+\t\t} else {\n+\t\t\t/* we are in a fixup/squash chain */\n \t\t\tconst char *p = opts->current_fixups.buf;\n \t\t\tint len = opts->current_fixups.len;\n \ndiff --git a/t/t3415-rebase-autosquash.sh b/t/t3415-rebase-autosquash.sh\nindex 7d5ea340b3..13f5688135 100755\n--- a/t/t3415-rebase-autosquash.sh\n+++ b/t/t3415-rebase-autosquash.sh\n@@ -330,7 +330,7 @@ test_expect_success 'wrapped original subject' '\n \ttest $base = $parent\n '\n \n-test_expect_failure 'abort last squash' '\n+test_expect_success 'abort last squash' '\n \ttest_when_finished \"test_might_fail git rebase --abort\" &&\n \ttest_when_finished \"git checkout master\" &&\n \n-- \ngitgitgadget\n"},{"id":"357305","messageId":"xmqqftypb44v.fsf@gitster-ct.c.googlers.com","threadId":"49265","inReplyTo":"0c9d0f75fc0dd28d55d4ed41d008182746fc86cd.1535759099.git.gitgitgadget@gmail.com","subject":"Re: [PATCH 2/2] rebase -i: be careful to wrap up fixup/squash chains","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-09-04T16:48:16Z","receivedAt":"2018-09-04T16:48:21Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"> diff --git a/sequencer.c b/sequencer.c\n> index 84bf598c3e..ac5c805c14 100644\n> --- a/sequencer.c\n> +++ b/sequencer.c\n> @@ -3578,9 +3578,20 @@ static int commit_staged_changes(struct replay_opts *opts,\n>  \t\t * the commit message and if there was a squash, let the user\n>  \t\t * edit it.\n>  \t\t */\n> -\t\tif (is_clean && !oidcmp(&head, &to_amend) &&\n> -\t\t    opts->current_fixup_count > 0 &&\n> -\t\t    file_exists(rebase_path_stopped_sha())) {\n> +\t\tif (!is_clean || !opts->current_fixup_count)\n> +\t\t\t; /* this is not the final fixup */\n> +\t\telse if (oidcmp(&head, &to_amend) ||\n> +\t\t\t !file_exists(rebase_path_stopped_sha())) {\n> +\t\t\t/* was a final fixup or squash done manually? */\n> +\t\t\tif (!is_fixup(peek_command(todo_list, 0))) {\n> +\t\t\t\tunlink(rebase_path_fixup_msg());\n> +\t\t\t\tunlink(rebase_path_squash_msg());\n> +\t\t\t\tunlink(rebase_path_current_fixups());\n> +\t\t\t\tstrbuf_reset(&opts->current_fixups);\n> +\t\t\t\topts->current_fixup_count = 0;\n> +\t\t\t}\n\nLet me see if the code is easily grokkable by (trying to) follow\naloud.\n\n    We used to refrain from going into this big else clause that\n    does the fixup-squash handling when is_clean is false,\n    current-count is not yet zero, head and to-amend are different\n    commits or stopped-sha file is missing.  The updated code still\n    refrains from going into the big else clause under exactly the\n    same condition, but it learned to clean up the state, when the\n    _next_ one is not a fix-up, i.e. when we are looking at the last\n    fixup/squash in the current chain.  And the lack of clean-up\n    would have resulted in the next step misbehaving.\n\nI see a few calls to is_fixup(peek_command()) and a local boolean\nvariable final_fixup used in this function.  I have to wonder if it\nmakes the resulting code, especially the above part, easier to\nfollow and understand, if the function peeked todo-list to check if\nwe are dealing with the final fix-up in a chain very early just\nonce, and used it to see \"are we doing the final fixup/squash in the\ncurrent chain?\" throughout the rest of the function.\n\n\tSide note: I actually think that the existing final_fixup\n\tboolean means something different (iow, final_fixup is not\n\tset inside the new \"clean-up\" code above, even though we\n\tdealt with the last one in the fix-up chain, and that is not\n\ta bug---which means that \"final_fixup\" does not mean \"we are\n\tdealing with the last one in the fix-up chain\"), which may\n\twant to be clarified a bit with in-code comment near where\n\tthe variable is defined for the function to be readable.\n\nIn any case, thanks for fixing this, which seems to have appeared in\nGit 2.18.  Let's fork a topic from maint, cook it in 'next' and aim\nfor eventually merging it down for both 2.19 and 2.18 tracks.\n\n> +\t\t} else {\n> +\t\t\t/* we are in a fixup/squash chain */\n>  \t\t\tconst char *p = opts->current_fixups.buf;\n>  \t\t\tint len = opts->current_fixups.len;\n>  \n> diff --git a/t/t3415-rebase-autosquash.sh b/t/t3415-rebase-autosquash.sh\n> index 7d5ea340b3..13f5688135 100755\n> --- a/t/t3415-rebase-autosquash.sh\n> +++ b/t/t3415-rebase-autosquash.sh\n> @@ -330,7 +330,7 @@ test_expect_success 'wrapped original subject' '\n>  \ttest $base = $parent\n>  '\n>  \n> -test_expect_failure 'abort last squash' '\n> +test_expect_success 'abort last squash' '\n>  \ttest_when_finished \"test_might_fail git rebase --abort\" &&\n>  \ttest_when_finished \"git checkout master\" &&\n"},{"id":"357327","messageId":"xmqqd0tt9j0s.fsf_-_@gitster-ct.c.googlers.com","threadId":"49265","inReplyTo":"8753c4e5fba5bb9cc42fdf438f4a69e702261a15.1535759099.git.gitgitgadget@gmail.com","subject":"Re*: [PATCH 1/2] rebase -i --autosquash: demonstrate a problem skipping the last squash","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-09-04T19:09:39Z","receivedAt":"2018-09-04T19:09:44Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Johannes Schindelin via GitGitGadget\" <gitgitgadget@gmail.com>\nwrites:\n\n> +\ttest_must_fail git -c core.editor=\"grep -q ^pick\" \\\n> +\t\trebase -ki --autosquash HEAD~4 &&\n\nWhen merged to 'pu', this reveals that \"git rebase\" rewritten in C\nknows \"--keep-empty\" but not \"-k\".\n\nI did a quick eyeballing between master:git-rebase.sh and\npu:builtin/rebase.c and I think that it is the only one that is\nmissed, but somebody may want to lend us a second set of eyes.\n\n-- >8 --\nSubject: rebase: re-add forgotten -k that stands for --keep-empty\n\n630a70ea (\"builtin rebase: support `keep-empty` option\", 2018-08-08)\nforgot that the option comes with a short-and-sweet -k synonym.  Add\nit back.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin/rebase.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 87590047b3..b26f9c10cf 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -847,7 +847,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\t\t &options.allow_rerere_autoupdate,\n \t\t\t N_(\"allow rerere to update index  with resolved \"\n \t\t\t    \"conflict\")),\n-\t\tOPT_BOOL(0, \"keep-empty\", &options.keep_empty,\n+\t\tOPT_BOOL('k', \"keep-empty\", &options.keep_empty,\n \t\t\t N_(\"preserve empty commits during rebase\")),\n \t\tOPT_BOOL(0, \"autosquash\", &options.autosquash,\n \t\t\t N_(\"move commits that begin with \"\n\n"},{"id":"357335","messageId":"nycvar.QRO.7.76.6.1809042145470.71@tvgsbejvaqbjf.bet","threadId":"49265","inReplyTo":"xmqqftypb44v.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH 2/2] rebase -i: be careful to wrap up fixup/squash chains","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2018-09-04T19:50:52Z","receivedAt":"2018-09-04T19:50:59Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Junio,\n\nOn Tue, 4 Sep 2018, Junio C Hamano wrote:\n\n> > diff --git a/sequencer.c b/sequencer.c\n> > index 84bf598c3e..ac5c805c14 100644\n> > --- a/sequencer.c\n> > +++ b/sequencer.c\n> > @@ -3578,9 +3578,20 @@ static int commit_staged_changes(struct replay_opts *opts,\n> >  \t\t * the commit message and if there was a squash, let the user\n> >  \t\t * edit it.\n> >  \t\t */\n> > -\t\tif (is_clean && !oidcmp(&head, &to_amend) &&\n> > -\t\t    opts->current_fixup_count > 0 &&\n> > -\t\t    file_exists(rebase_path_stopped_sha())) {\n> > +\t\tif (!is_clean || !opts->current_fixup_count)\n> > +\t\t\t; /* this is not the final fixup */\n> > +\t\telse if (oidcmp(&head, &to_amend) ||\n> > +\t\t\t !file_exists(rebase_path_stopped_sha())) {\n> > +\t\t\t/* was a final fixup or squash done manually? */\n> > +\t\t\tif (!is_fixup(peek_command(todo_list, 0))) {\n> > +\t\t\t\tunlink(rebase_path_fixup_msg());\n> > +\t\t\t\tunlink(rebase_path_squash_msg());\n> > +\t\t\t\tunlink(rebase_path_current_fixups());\n> > +\t\t\t\tstrbuf_reset(&opts->current_fixups);\n> > +\t\t\t\topts->current_fixup_count = 0;\n> > +\t\t\t}\n> \n> Let me see if the code is easily grokkable by (trying to) follow\n> aloud.\n> \n>     We used to refrain from going into this big else clause that\n>     does the fixup-squash handling when is_clean is false,\n>     current-count is not yet zero, head and to-amend are different\n\ns/not yet zero/still zero/\n\n>     commits or stopped-sha file is missing.  The updated code still\n>     refrains from going into the big else clause under exactly the\n>     same condition, but it learned to clean up the state, when the\n>     _next_ one is not a fix-up, i.e. when we are looking at the last\n>     fixup/squash in the current chain.  And the lack of clean-up\n>     would have resulted in the next step misbehaving.\n\ns/next step/ next fixup or squash chain, if any,/\n\nYou got the gist right.\n\n> I see a few calls to is_fixup(peek_command()) and a local boolean\n> variable final_fixup used in this function.  I have to wonder if it\n> makes the resulting code, especially the above part, easier to\n> follow and understand, if the function peeked todo-list to check if\n> we are dealing with the final fix-up in a chain very early just\n> once, and used it to see \"are we doing the final fixup/squash in the\n> current chain?\" throughout the rest of the function.\n> \n> \tSide note: I actually think that the existing final_fixup\n> \tboolean means something different (iow, final_fixup is not\n> \tset inside the new \"clean-up\" code above, even though we\n> \tdealt with the last one in the fix-up chain, and that is not\n> \ta bug---which means that \"final_fixup\" does not mean \"we are\n> \tdealing with the last one in the fix-up chain\"), which may\n> \twant to be clarified a bit with in-code comment near where\n> \tthe variable is defined for the function to be readable.\n\nIndeed. The `final_fixup` name tries to convey \"need to finalize the final\nfixup\", as in: show the commit message in an editor if any squash! commits\nwere included, and otherwise simply clean the commit message of all those\ncommented-out lines.\n\nSo that's very different from \"is the previously-run todo command a final\nfixup in a fixup/squash chain?\"\n\n> In any case, thanks for fixing this, which seems to have appeared in\n> Git 2.18.  Let's fork a topic from maint, cook it in 'next' and aim\n> for eventually merging it down for both 2.19 and 2.18 tracks.\n\nSounds good,\nDscho\n\n> \n> > +\t\t} else {\n> > +\t\t\t/* we are in a fixup/squash chain */\n> >  \t\t\tconst char *p = opts->current_fixups.buf;\n> >  \t\t\tint len = opts->current_fixups.len;\n> >  \n> > diff --git a/t/t3415-rebase-autosquash.sh b/t/t3415-rebase-autosquash.sh\n> > index 7d5ea340b3..13f5688135 100755\n> > --- a/t/t3415-rebase-autosquash.sh\n> > +++ b/t/t3415-rebase-autosquash.sh\n> > @@ -330,7 +330,7 @@ test_expect_success 'wrapped original subject' '\n> >  \ttest $base = $parent\n> >  '\n> >  \n> > -test_expect_failure 'abort last squash' '\n> > +test_expect_success 'abort last squash' '\n> >  \ttest_when_finished \"test_might_fail git rebase --abort\" &&\n> >  \ttest_when_finished \"git checkout master\" &&\n> \n"},{"id":"357386","messageId":"nycvar.QRO.7.76.6.1809050025480.71@tvgsbejvaqbjf.bet","threadId":"49265","inReplyTo":"xmqqd0tt9j0s.fsf_-_@gitster-ct.c.googlers.com","subject":"Re: Re*: [PATCH 1/2] rebase -i --autosquash: demonstrate a problem skipping the last squash","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2018-09-04T22:27:58Z","receivedAt":"2018-09-04T22:28:06Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Junio,\n\nOn Tue, 4 Sep 2018, Junio C Hamano wrote:\n\n> \"Johannes Schindelin via GitGitGadget\" <gitgitgadget@gmail.com>\n> writes:\n> \n> > +\ttest_must_fail git -c core.editor=\"grep -q ^pick\" \\\n> > +\t\trebase -ki --autosquash HEAD~4 &&\n> \n> When merged to 'pu', this reveals that \"git rebase\" rewritten in C\n> knows \"--keep-empty\" but not \"-k\".\n\nI had already reported this:\n\nhttps://public-inbox.org/git/nycvar.QRO.7.76.6.1808241803100.73@tvgsbejvaqbjf.bet/\n\n> \n> I did a quick eyeballing between master:git-rebase.sh and\n> pu:builtin/rebase.c and I think that it is the only one that is\n> missed, but somebody may want to lend us a second set of eyes.\n> \n> -- >8 --\n> Subject: rebase: re-add forgotten -k that stands for --keep-empty\n> \n> 630a70ea (\"builtin rebase: support `keep-empty` option\", 2018-08-08)\n> forgot that the option comes with a short-and-sweet -k synonym.  Add\n> it back.\n> \n> Signed-off-by: Junio C Hamano <gitster@pobox.com>\n\nSince this is not in `next` yet, let's do it the correct way. I had a\nfixup! sitting in my wip-rebase branch all the time, I just needed to find\nthe time and motivation to figure out how to let GitGitGadget send a v2\nwhen v1 was not sent via GitGitGadget.\n\nCiao,\nDscho\n\n> ---\n>  builtin/rebase.c | 2 +-\n>  1 file changed, 1 insertion(+), 1 deletion(-)\n> \n> diff --git a/builtin/rebase.c b/builtin/rebase.c\n> index 87590047b3..b26f9c10cf 100644\n> --- a/builtin/rebase.c\n> +++ b/builtin/rebase.c\n> @@ -847,7 +847,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>  \t\t\t &options.allow_rerere_autoupdate,\n>  \t\t\t N_(\"allow rerere to update index  with resolved \"\n>  \t\t\t    \"conflict\")),\n> -\t\tOPT_BOOL(0, \"keep-empty\", &options.keep_empty,\n> +\t\tOPT_BOOL('k', \"keep-empty\", &options.keep_empty,\n>  \t\t\t N_(\"preserve empty commits during rebase\")),\n>  \t\tOPT_BOOL(0, \"autosquash\", &options.autosquash,\n>  \t\t\t N_(\"move commits that begin with \"\n> \n> \n"},{"id":"357441","messageId":"xmqqin3j6h9j.fsf@gitster-ct.c.googlers.com","threadId":"49265","inReplyTo":"nycvar.QRO.7.76.6.1809050025480.71@tvgsbejvaqbjf.bet","subject":"Re: Re*: [PATCH 1/2] rebase -i --autosquash: demonstrate a problem skipping the last squash","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-09-05T16:28:08Z","receivedAt":"2018-09-05T16:28:13Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> On Tue, 4 Sep 2018, Junio C Hamano wrote:\n>\n>> \"Johannes Schindelin via GitGitGadget\" <gitgitgadget@gmail.com>\n>> writes:\n>> \n>> > +\ttest_must_fail git -c core.editor=\"grep -q ^pick\" \\\n>> > +\t\trebase -ki --autosquash HEAD~4 &&\n>> \n>> When merged to 'pu', this reveals that \"git rebase\" rewritten in C\n>> knows \"--keep-empty\" but not \"-k\".\n>\n> I had already reported this:\n>\n> https://public-inbox.org/git/nycvar.QRO.7.76.6.1808241803100.73@tvgsbejvaqbjf.bet/\n\nGood that you said there that you'll have it fixed in future updates.\n\nI do not want to leave the project state with failing test at the\ntip of 'pu', and I do not want to get distracted in squashing the\nfix deep in large sequences of topics that we know will be rerolled\nonce the prerelease freeze is over anyway, so in the meantime I'll\nqueue this near the tip of 'pu' to keep the tree sane.\n\nThanks for eyeballing.\n"}]}