{"thread":{"id":"50341","subject":"[PATCH] rebase -x: sanity check command","startedAt":"2019-01-28T10:26:20Z","lastAt":"2021-03-23T20:53:11Z","messageCount":31,"participants":["Phillip Wood","Junio C Hamano","Johannes Schindelin","Ævar Arnfjörð Bjarmason"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"367820","messageId":"20190128102620.18222-1-phillip.wood@talktalk.net","threadId":"50341","inReplyTo":null,"subject":"[PATCH] rebase -x: sanity check command","fromName":"Phillip Wood","fromEmail":"phillip.wood@talktalk.net","sentAt":"2019-01-28T10:26:20Z","receivedAt":"2019-01-28T10:26:20Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Phillip Wood <phillip.wood@dunelm.org.uk>\n\nIf the user gives an empty argument to --exec then the rebase starts to\nrun before erroring out with\n\n  error: missing arguments for exec\n  error: invalid line 2: exec\n  You can fix this with 'git rebase --edit-todo' and then run 'git rebase --continue'.\n  Or you can abort the rebase with 'git rebase --abort'.\n\nInstead check for empty commands before starting the rebase.\n\nAlso check that the command does not contain any newlines as the\ntodo-list format is unable to cope with multiline commands. Note that\nthis changes the behavior, before this change one could do\n\ngit rebase --exec='echo one\nexec echo two'\n\nand it would insert two exec lines in the todo list, now it will error\nout.\n\nSigned-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n---\n builtin/rebase.c              | 22 ++++++++++++++++++++++\n t/t3404-rebase-interactive.sh | 19 +++++++++++++++++++\n 2 files changed, 41 insertions(+)\n\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 00de70365e..b6c54b03c1 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -793,6 +793,24 @@ static void set_reflog_action(struct rebase_options *options)\n \tstrbuf_release(&buf);\n }\n \n+static int check_exec_cmd(const char *cmd)\n+{\n+\tint non_blank = 0;\n+\n+\twhile (*cmd) {\n+\t\tif (*cmd == '\\n')\n+\t\t\treturn error(_(\"exec commands cannot contain newlines\"));\n+\t\tif (!isspace(*cmd))\n+\t\t\tnon_blank = 1;\n+\t\tcmd++;\n+\t}\n+\n+\tif (non_blank)\n+\t\treturn 0;\n+\n+\treturn error(_(\"empty exec command\"));\n+}\n+\n int cmd_rebase(int argc, const char **argv, const char *prefix)\n {\n \tstruct rebase_options options = {\n@@ -1130,6 +1148,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\t}\n \t}\n \n+\tfor (i = 0; i < exec.nr; i++)\n+\t\tif (check_exec_cmd(exec.items[i].string))\n+\t\t\texit(1);\n+\n \tif (!(options.flags & REBASE_NO_QUIET))\n \t\targv_array_push(&options.git_am_opts, \"-q\");\n \ndiff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\nindex 7a440e08d8..c98f64eb2d 100755\n--- a/t/t3404-rebase-interactive.sh\n+++ b/t/t3404-rebase-interactive.sh\n@@ -147,6 +147,25 @@ test_expect_success 'rebase -i with the exec command checks tree cleanness' '\n \tgit rebase --continue\n '\n \n+test_expect_success 'rebase -x with empty command fails' '\n+\ttest_when_finished \"git rebase --abort ||:\" &&\n+\ttest_must_fail git rebase -x \"\" @ 2>actual &&\n+\ttest_write_lines \"error: empty exec command\" >expected &&\n+\ttest_i18ncmp expected actual &&\n+\ttest_must_fail git rebase -x \" \" @ 2>actual &&\n+\ttest_i18ncmp expected actual\n+'\n+\n+LF='\n+'\n+test_expect_success 'rebase -x with newline in command fails' '\n+\ttest_when_finished \"git rebase --abort ||:\" &&\n+\ttest_must_fail git rebase -x \"a${LF}b\" @ 2>actual &&\n+\ttest_write_lines \"error: exec commands cannot contain newlines\" \\\n+\t\t\t >expected &&\n+\ttest_i18ncmp expected actual\n+'\n+\n test_expect_success 'rebase -i with exec of inexistent command' '\n \tgit checkout master &&\n \ttest_when_finished \"git rebase --abort\" &&\n-- \n2.20.1\n\n"},{"id":"367851","messageId":"xmqqd0ogbpzn.fsf@gitster-ct.c.googlers.com","threadId":"50341","inReplyTo":"20190128102620.18222-1-phillip.wood@talktalk.net","subject":"Re: [PATCH] rebase -x: sanity check command","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-01-28T18:23:40Z","receivedAt":"2019-01-28T18:23:45Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Phillip Wood <phillip.wood@talktalk.net> writes:\n\n> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n>\n> If the user gives an empty argument to --exec then the rebase starts to\n> run before erroring out with\n>\n>   error: missing arguments for exec\n>   error: invalid line 2: exec\n>   You can fix this with 'git rebase --edit-todo' and then run 'git rebase --continue'.\n>   Or you can abort the rebase with 'git rebase --abort'.\n\nHmph.  I do agree that the above makes an unfortunate end-user\nexperience, but I would sort-of imagine that it would even be nicer\nfor such an empty exec to behave as if it were \"exec false\" but with\nless severe error message, i.e. a way for the user to say \"I want to\nbreak the sequence here and get an interactive session\".  We may not\neven need to add the \"break\" insn if we go that way and there is one\nless thing for users to learn.  I dunno, but I tend to prefer giving\na useful and safe behaviour to interactive users other than erroring\nout, when there _is_ such a safe behaviour that is obvious from the\nsituation, and I feel that an empty \"exec\" is such a case.\n\n> Also check that the command does not contain any newlines as the\n> todo-list format is unable to cope with multiline commands. Note that\n> this changes the behavior, before this change one could do\n>\n> git rebase --exec='echo one\n> exec echo two'\n\nIt is very good to check the input, regardless of what an empty\n\"exec\" should do.\n"},{"id":"367891","messageId":"nycvar.QRO.7.76.6.1901282253200.41@tvgsbejvaqbjf.bet","threadId":"50341","inReplyTo":"xmqqd0ogbpzn.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH] rebase -x: sanity check command","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2019-01-28T21:56:05Z","receivedAt":"2019-01-28T21:56:32Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Junio,\n\nOn Mon, 28 Jan 2019, Junio C Hamano wrote:\n\n> Phillip Wood <phillip.wood@talktalk.net> writes:\n> \n> > From: Phillip Wood <phillip.wood@dunelm.org.uk>\n> >\n> > If the user gives an empty argument to --exec then the rebase starts to\n> > run before erroring out with\n> >\n> >   error: missing arguments for exec\n> >   error: invalid line 2: exec\n> >   You can fix this with 'git rebase --edit-todo' and then run 'git rebase --continue'.\n> >   Or you can abort the rebase with 'git rebase --abort'.\n> \n> Hmph.  I do agree that the above makes an unfortunate end-user\n> experience, but I would sort-of imagine that it would even be nicer\n> for such an empty exec to behave as if it were \"exec false\" but with\n> less severe error message, i.e. a way for the user to say \"I want to\n> break the sequence here and get an interactive session\".  We may not\n> even need to add the \"break\" insn if we go that way and there is one\n> less thing for users to learn.  I dunno, but I tend to prefer giving\n> a useful and safe behaviour to interactive users other than erroring\n> out, when there _is_ such a safe behaviour that is obvious from the\n> situation, and I feel that an empty \"exec\" is such a case.\n\nThat would make things unnecessarily confusing. An empty command is not\n`false` with a gentler error message. An empty command is a missing\ncommand.\n\nI am, however, concerned that special-casing an empty command will not\nmake things better: if the user called `git rebase --exec=fasle`, they\nwill *still* have to clean up their edit script.\n\nOr just `git rebase --abort`, which I would do whether I had forgotten to\nspecify a command or whether I had a typo in my command.\n\n> > Also check that the command does not contain any newlines as the\n> > todo-list format is unable to cope with multiline commands. Note that\n> > this changes the behavior, before this change one could do\n> >\n> > git rebase --exec='echo one\n> > exec echo two'\n> \n> It is very good to check the input, regardless of what an empty\n> \"exec\" should do.\n\nShould we then also check for incorrect quoting, missing commands, other\nerrors? I am not sure that this path leads to sanity.\n\nCiao,\nDscho\n"},{"id":"367893","messageId":"nycvar.QRO.7.76.6.1901282257570.41@tvgsbejvaqbjf.bet","threadId":"50341","inReplyTo":"20190128102620.18222-1-phillip.wood@talktalk.net","subject":"Re: [PATCH] rebase -x: sanity check command","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2019-01-28T22:03:30Z","receivedAt":"2019-01-28T22:03:54Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Phillip,\n\nOn Mon, 28 Jan 2019, Phillip Wood wrote:\n\n> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n> \n> If the user gives an empty argument to --exec then the rebase starts to\n> run before erroring out with\n> \n>   error: missing arguments for exec\n>   error: invalid line 2: exec\n>   You can fix this with 'git rebase --edit-todo' and then run 'git rebase --continue'.\n>   Or you can abort the rebase with 'git rebase --abort'.\n\nAnd that's the same if you specify an incorrect command.\n\nIn both cases, I would probably heed the second line of the advice: git\nrebase --abort.\n\n> Instead check for empty commands before starting the rebase.\n> \n> Also check that the command does not contain any newlines as the\n> todo-list format is unable to cope with multiline commands. Note that\n> this changes the behavior, before this change one could do\n> \n> git rebase --exec='echo one\n> exec echo two'\n> \n> and it would insert two exec lines in the todo list, now it will error\n> out.\n\nThis, however, makes a ton of sense to me.\n\n> diff --git a/builtin/rebase.c b/builtin/rebase.c\n> index 00de70365e..b6c54b03c1 100644\n> --- a/builtin/rebase.c\n> +++ b/builtin/rebase.c\n> @@ -793,6 +793,24 @@ static void set_reflog_action(struct rebase_options *options)\n>  \tstrbuf_release(&buf);\n>  }\n>  \n> +static int check_exec_cmd(const char *cmd)\n> +{\n> +\tint non_blank = 0;\n> +\n> +\twhile (*cmd) {\n> +\t\tif (*cmd == '\\n')\n> +\t\t\treturn error(_(\"exec commands cannot contain newlines\"));\n> +\t\tif (!isspace(*cmd))\n> +\t\t\tnon_blank = 1;\n> +\t\tcmd++;\n> +\t}\n> +\n> +\tif (non_blank)\n> +\t\treturn 0;\n\nWe are not in a performance critical path here, so I would prefer the\nreadability of this code:\n\n\tif (strchr(cmd, '\\n'))\n\t\treturn error(...);\n\nAnd if you *really* must,\n\n\t/* Does the command consist purely of whitespace? */\n\tif (!cmd[strspn(cmd, \" \\t\\r\\n\")])\n\t\treturn error(...);\n\nBut as I suggested also in a reply to Junio's answer: where would we stop\nto validate the commands?\n\nCiao,\nDscho\n\n> +\n> +\treturn error(_(\"empty exec command\"));\n> +}\n> +\n>  int cmd_rebase(int argc, const char **argv, const char *prefix)\n>  {\n>  \tstruct rebase_options options = {\n> @@ -1130,6 +1148,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>  \t\t}\n>  \t}\n>  \n> +\tfor (i = 0; i < exec.nr; i++)\n> +\t\tif (check_exec_cmd(exec.items[i].string))\n> +\t\t\texit(1);\n> +\n>  \tif (!(options.flags & REBASE_NO_QUIET))\n>  \t\targv_array_push(&options.git_am_opts, \"-q\");\n>  \n> diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\n> index 7a440e08d8..c98f64eb2d 100755\n> --- a/t/t3404-rebase-interactive.sh\n> +++ b/t/t3404-rebase-interactive.sh\n> @@ -147,6 +147,25 @@ test_expect_success 'rebase -i with the exec command checks tree cleanness' '\n>  \tgit rebase --continue\n>  '\n>  \n> +test_expect_success 'rebase -x with empty command fails' '\n> +\ttest_when_finished \"git rebase --abort ||:\" &&\n> +\ttest_must_fail git rebase -x \"\" @ 2>actual &&\n> +\ttest_write_lines \"error: empty exec command\" >expected &&\n> +\ttest_i18ncmp expected actual &&\n> +\ttest_must_fail git rebase -x \" \" @ 2>actual &&\n> +\ttest_i18ncmp expected actual\n> +'\n> +\n> +LF='\n> +'\n> +test_expect_success 'rebase -x with newline in command fails' '\n> +\ttest_when_finished \"git rebase --abort ||:\" &&\n> +\ttest_must_fail git rebase -x \"a${LF}b\" @ 2>actual &&\n> +\ttest_write_lines \"error: exec commands cannot contain newlines\" \\\n> +\t\t\t >expected &&\n> +\ttest_i18ncmp expected actual\n> +'\n> +\n>  test_expect_success 'rebase -i with exec of inexistent command' '\n>  \tgit checkout master &&\n>  \ttest_when_finished \"git rebase --abort\" &&\n> -- \n> 2.20.1\n> \n> \n"},{"id":"367947","messageId":"13f14cc6-e437-3f18-7f24-1d6edda1cb23@talktalk.net","threadId":"50341","inReplyTo":"nycvar.QRO.7.76.6.1901282257570.41@tvgsbejvaqbjf.bet","subject":"Re: [PATCH] rebase -x: sanity check command","fromName":"Phillip Wood","fromEmail":"phillip.wood@talktalk.net","sentAt":"2019-01-29T11:34:22Z","receivedAt":"2019-01-29T11:34:14Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Dscho\n\nOn 28/01/2019 22:03, Johannes Schindelin wrote:\n> Hi Phillip,\n> \n> On Mon, 28 Jan 2019, Phillip Wood wrote:\n> \n>> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n>>\n>> If the user gives an empty argument to --exec then the rebase starts to\n>> run before erroring out with\n>>\n>>   error: missing arguments for exec\n>>   error: invalid line 2: exec\n>>   You can fix this with 'git rebase --edit-todo' and then run 'git rebase --continue'.\n>>   Or you can abort the rebase with 'git rebase --abort'.\n> \n> And that's the same if you specify an incorrect command.\n\nNot quite, the issue is that the todo list is invalid, not that the\ncommand fails - it never gets that far. Those errors are coming from\nparse_insn_line() and parse_insn_buffer().\n\n> \n> In both cases, I would probably heed the second line of the advice: git\n> rebase --abort.\n> \n>> Instead check for empty commands before starting the rebase.\n>>\n>> Also check that the command does not contain any newlines as the\n>> todo-list format is unable to cope with multiline commands. Note that\n>> this changes the behavior, before this change one could do\n>>\n>> git rebase --exec='echo one\n>> exec echo two'\n>>\n>> and it would insert two exec lines in the todo list, now it will error\n>> out.\n> \n> This, however, makes a ton of sense to me.\n> \n>> diff --git a/builtin/rebase.c b/builtin/rebase.c\n>> index 00de70365e..b6c54b03c1 100644\n>> --- a/builtin/rebase.c\n>> +++ b/builtin/rebase.c\n>> @@ -793,6 +793,24 @@ static void set_reflog_action(struct rebase_options *options)\n>>  \tstrbuf_release(&buf);\n>>  }\n>>  \n>> +static int check_exec_cmd(const char *cmd)\n>> +{\n>> +\tint non_blank = 0;\n>> +\n>> +\twhile (*cmd) {\n>> +\t\tif (*cmd == '\\n')\n>> +\t\t\treturn error(_(\"exec commands cannot contain newlines\"));\n>> +\t\tif (!isspace(*cmd))\n>> +\t\t\tnon_blank = 1;\n>> +\t\tcmd++;\n>> +\t}\n>> +\n>> +\tif (non_blank)\n>> +\t\treturn 0;\n> \n> We are not in a performance critical path here, so I would prefer the\n> readability of this code:\n> \n> \tif (strchr(cmd, '\\n'))\n> \t\treturn error(...);\n> \n> And if you *really* must,\n> \n> \t/* Does the command consist purely of whitespace? */\n> \tif (!cmd[strspn(cmd, \" \\t\\r\\n\")])\n> \t\treturn error(...);\n> \n> But as I suggested also in a reply to Junio's answer: where would we stop\n> to validate the commands?\n\nI'm not trying to validate the command (and I don't think we can/should)\n- just generate a todo list that can be parsed.\n\nBest Wishes\n\nPhillip\n\n> \n> Ciao,\n> Dscho\n> \n>> +\n>> +\treturn error(_(\"empty exec command\"));\n>> +}\n>> +\n>>  int cmd_rebase(int argc, const char **argv, const char *prefix)\n>>  {\n>>  \tstruct rebase_options options = {\n>> @@ -1130,6 +1148,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>>  \t\t}\n>>  \t}\n>>  \n>> +\tfor (i = 0; i < exec.nr; i++)\n>> +\t\tif (check_exec_cmd(exec.items[i].string))\n>> +\t\t\texit(1);\n>> +\n>>  \tif (!(options.flags & REBASE_NO_QUIET))\n>>  \t\targv_array_push(&options.git_am_opts, \"-q\");\n>>  \n>> diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\n>> index 7a440e08d8..c98f64eb2d 100755\n>> --- a/t/t3404-rebase-interactive.sh\n>> +++ b/t/t3404-rebase-interactive.sh\n>> @@ -147,6 +147,25 @@ test_expect_success 'rebase -i with the exec command checks tree cleanness' '\n>>  \tgit rebase --continue\n>>  '\n>>  \n>> +test_expect_success 'rebase -x with empty command fails' '\n>> +\ttest_when_finished \"git rebase --abort ||:\" &&\n>> +\ttest_must_fail git rebase -x \"\" @ 2>actual &&\n>> +\ttest_write_lines \"error: empty exec command\" >expected &&\n>> +\ttest_i18ncmp expected actual &&\n>> +\ttest_must_fail git rebase -x \" \" @ 2>actual &&\n>> +\ttest_i18ncmp expected actual\n>> +'\n>> +\n>> +LF='\n>> +'\n>> +test_expect_success 'rebase -x with newline in command fails' '\n>> +\ttest_when_finished \"git rebase --abort ||:\" &&\n>> +\ttest_must_fail git rebase -x \"a${LF}b\" @ 2>actual &&\n>> +\ttest_write_lines \"error: exec commands cannot contain newlines\" \\\n>> +\t\t\t >expected &&\n>> +\ttest_i18ncmp expected actual\n>> +'\n>> +\n>>  test_expect_success 'rebase -i with exec of inexistent command' '\n>>  \tgit checkout master &&\n>>  \ttest_when_finished \"git rebase --abort\" &&\n>> -- \n>> 2.20.1\n>>\n>>\n\n"},{"id":"367949","messageId":"4e4e46b3-9745-a3db-56cb-58763f7cf994@talktalk.net","threadId":"50341","inReplyTo":"nycvar.QRO.7.76.6.1901282253200.41@tvgsbejvaqbjf.bet","subject":"Re: [PATCH] rebase -x: sanity check command","fromName":"Phillip Wood","fromEmail":"phillip.wood@talktalk.net","sentAt":"2019-01-29T11:40:02Z","receivedAt":"2019-01-29T12:07:57Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Dear Junio & Dscho\n\nOn 28/01/2019 21:56, Johannes Schindelin wrote:\n> Hi Junio,\n> \n> On Mon, 28 Jan 2019, Junio C Hamano wrote:\n> \n>> Phillip Wood <phillip.wood@talktalk.net> writes:\n>>\n>>> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n>>>\n>>> If the user gives an empty argument to --exec then the rebase starts to\n>>> run before erroring out with\n>>>\n>>>   error: missing arguments for exec\n>>>   error: invalid line 2: exec\n>>>   You can fix this with 'git rebase --edit-todo' and then run 'git rebase --continue'.\n>>>   Or you can abort the rebase with 'git rebase --abort'.\n>>\n>> Hmph.  I do agree that the above makes an unfortunate end-user\n>> experience, but I would sort-of imagine that it would even be nicer\n>> for such an empty exec to behave as if it were \"exec false\" but with\n>> less severe error message, i.e. a way for the user to say \"I want to\n>> break the sequence here and get an interactive session\".  We may not\n>> even need to add the \"break\" insn if we go that way and there is one\n>> less thing for users to learn.  I dunno, but I tend to prefer giving\n>> a useful and safe behaviour to interactive users other than erroring\n>> out, when there _is_ such a safe behaviour that is obvious from the\n>> situation, and I feel that an empty \"exec\" is such a case.\n> \n> That would make things unnecessarily confusing. An empty command is not\n> `false` with a gentler error message. An empty command is a missing\n> command.\n\nI agree that having a special meaning to the empty command would be\nconfusing. Also giving it on the command line only helps if you want to\nstop after each pick and my impression is that people want to break\nafter specific commits to amend a fixup or something like that.\n\n> I am, however, concerned that special-casing an empty command will not\n> make things better: if the user called `git rebase --exec=fasle`, they\n> will *still* have to clean up their edit script.\n\nThe empty commands create an invalid todo list which git cannot parse,\nthis patch is not a step down the path of checking that the command\nexists or is valid shell - I don't think that would be possible in the\ngeneral case.\n\nBest Wishes\n\nPhillip\n\n> Or just `git rebase --abort`, which I would do whether I had forgotten to\n> specify a command or whether I had a typo in my command.\n> \n>>> Also check that the command does not contain any newlines as the\n>>> todo-list format is unable to cope with multiline commands. Note that\n>>> this changes the behavior, before this change one could do\n>>>\n>>> git rebase --exec='echo one\n>>> exec echo two'\n>>\n>> It is very good to check the input, regardless of what an empty\n>> \"exec\" should do.\n> \n> Should we then also check for incorrect quoting, missing commands, other\n> errors? I am not sure that this path leads to sanity.\n> \n> Ciao,\n> Dscho\n> \n\n"},{"id":"368005","messageId":"nycvar.QRO.7.76.6.1901291632070.41@tvgsbejvaqbjf.bet","threadId":"50341","inReplyTo":"13f14cc6-e437-3f18-7f24-1d6edda1cb23@talktalk.net","subject":"Re: [PATCH] rebase -x: sanity check command","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2019-01-29T15:32:45Z","receivedAt":"2019-01-29T15:33:11Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Phillip,\n\n[sorry for the double-send, I dropped the Cc: list by mistake the first\ntime I replied]\n\nOn Tue, 29 Jan 2019, Phillip Wood wrote:\n\n> On 28/01/2019 22:03, Johannes Schindelin wrote:\n> > Hi Phillip,\n> > \n> > On Mon, 28 Jan 2019, Phillip Wood wrote:\n> > \n> >> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n> >>\n> >> If the user gives an empty argument to --exec then the rebase starts to\n> >> run before erroring out with\n> >>\n> >>   error: missing arguments for exec\n> >>   error: invalid line 2: exec\n> >>   You can fix this with 'git rebase --edit-todo' and then run 'git rebase --continue'.\n> >>   Or you can abort the rebase with 'git rebase --abort'.\n> > \n> > And that's the same if you specify an incorrect command.\n> \n> Not quite, the issue is that the todo list is invalid, not that the\n> command fails - it never gets that far. Those errors are coming from\n> parse_insn_line() and parse_insn_buffer().\n\nAh! I misunderstood \"then the rebase starts to run\" part.\n\nSo please let me withdraw my objections to catch this error.\n\nHowever, I still would highly recommend to use `strspn()` to simplify the\ncode.\n\nThanks,\nDscho\n\n> > In both cases, I would probably heed the second line of the advice: git\n> > rebase --abort.\n> > \n> >> Instead check for empty commands before starting the rebase.\n> >>\n> >> Also check that the command does not contain any newlines as the\n> >> todo-list format is unable to cope with multiline commands. Note that\n> >> this changes the behavior, before this change one could do\n> >>\n> >> git rebase --exec='echo one\n> >> exec echo two'\n> >>\n> >> and it would insert two exec lines in the todo list, now it will error\n> >> out.\n> > \n> > This, however, makes a ton of sense to me.\n> > \n> >> diff --git a/builtin/rebase.c b/builtin/rebase.c\n> >> index 00de70365e..b6c54b03c1 100644\n> >> --- a/builtin/rebase.c\n> >> +++ b/builtin/rebase.c\n> >> @@ -793,6 +793,24 @@ static void set_reflog_action(struct rebase_options *options)\n> >>  \tstrbuf_release(&buf);\n> >>  }\n> >>  \n> >> +static int check_exec_cmd(const char *cmd)\n> >> +{\n> >> +\tint non_blank = 0;\n> >> +\n> >> +\twhile (*cmd) {\n> >> +\t\tif (*cmd == '\\n')\n> >> +\t\t\treturn error(_(\"exec commands cannot contain newlines\"));\n> >> +\t\tif (!isspace(*cmd))\n> >> +\t\t\tnon_blank = 1;\n> >> +\t\tcmd++;\n> >> +\t}\n> >> +\n> >> +\tif (non_blank)\n> >> +\t\treturn 0;\n> > \n> > We are not in a performance critical path here, so I would prefer the\n> > readability of this code:\n> > \n> > \tif (strchr(cmd, '\\n'))\n> > \t\treturn error(...);\n> > \n> > And if you *really* must,\n> > \n> > \t/* Does the command consist purely of whitespace? */\n> > \tif (!cmd[strspn(cmd, \" \\t\\r\\n\")])\n> > \t\treturn error(...);\n> > \n> > But as I suggested also in a reply to Junio's answer: where would we stop\n> > to validate the commands?\n> \n> I'm not trying to validate the command (and I don't think we can/should)\n> - just generate a todo list that can be parsed.\n> \n> Best Wishes\n> \n> Phillip\n> \n> > \n> > Ciao,\n> > Dscho\n> > \n> >> +\n> >> +\treturn error(_(\"empty exec command\"));\n> >> +}\n> >> +\n> >>  int cmd_rebase(int argc, const char **argv, const char *prefix)\n> >>  {\n> >>  \tstruct rebase_options options = {\n> >> @@ -1130,6 +1148,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n> >>  \t\t}\n> >>  \t}\n> >>  \n> >> +\tfor (i = 0; i < exec.nr; i++)\n> >> +\t\tif (check_exec_cmd(exec.items[i].string))\n> >> +\t\t\texit(1);\n> >> +\n> >>  \tif (!(options.flags & REBASE_NO_QUIET))\n> >>  \t\targv_array_push(&options.git_am_opts, \"-q\");\n> >>  \n> >> diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\n> >> index 7a440e08d8..c98f64eb2d 100755\n> >> --- a/t/t3404-rebase-interactive.sh\n> >> +++ b/t/t3404-rebase-interactive.sh\n> >> @@ -147,6 +147,25 @@ test_expect_success 'rebase -i with the exec command checks tree cleanness' '\n> >>  \tgit rebase --continue\n> >>  '\n> >>  \n> >> +test_expect_success 'rebase -x with empty command fails' '\n> >> +\ttest_when_finished \"git rebase --abort ||:\" &&\n> >> +\ttest_must_fail git rebase -x \"\" @ 2>actual &&\n> >> +\ttest_write_lines \"error: empty exec command\" >expected &&\n> >> +\ttest_i18ncmp expected actual &&\n> >> +\ttest_must_fail git rebase -x \" \" @ 2>actual &&\n> >> +\ttest_i18ncmp expected actual\n> >> +'\n> >> +\n> >> +LF='\n> >> +'\n> >> +test_expect_success 'rebase -x with newline in command fails' '\n> >> +\ttest_when_finished \"git rebase --abort ||:\" &&\n> >> +\ttest_must_fail git rebase -x \"a${LF}b\" @ 2>actual &&\n> >> +\ttest_write_lines \"error: exec commands cannot contain newlines\" \\\n> >> +\t\t\t >expected &&\n> >> +\ttest_i18ncmp expected actual\n> >> +'\n> >> +\n> >>  test_expect_success 'rebase -i with exec of inexistent command' '\n> >>  \tgit checkout master &&\n> >>  \ttest_when_finished \"git rebase --abort\" &&\n> >> -- \n> >> 2.20.1\n> >>\n> >>\n> \n> \n"},{"id":"368006","messageId":"nycvar.QRO.7.76.6.1901291633440.41@tvgsbejvaqbjf.bet","threadId":"50341","inReplyTo":"4e4e46b3-9745-a3db-56cb-58763f7cf994@talktalk.net","subject":"Re: [PATCH] rebase -x: sanity check command","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2019-01-29T15:35:37Z","receivedAt":"2019-01-29T15:36:03Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Phillip,\n\nOn Tue, 29 Jan 2019, Phillip Wood wrote:\n\n> On 28/01/2019 21:56, Johannes Schindelin wrote:\n> > \n> > On Mon, 28 Jan 2019, Junio C Hamano wrote:\n> > \n> >> Phillip Wood <phillip.wood@talktalk.net> writes:\n> >>\n> >>> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n> >>>\n> >>> If the user gives an empty argument to --exec then the rebase starts to\n> >>> run before erroring out with\n> >>>\n> >>>   error: missing arguments for exec\n> >>>   error: invalid line 2: exec\n> >>>   You can fix this with 'git rebase --edit-todo' and then run 'git rebase --continue'.\n> >>>   Or you can abort the rebase with 'git rebase --abort'.\n> >>\n> >> Hmph.  I do agree that the above makes an unfortunate end-user\n> >> experience, but I would sort-of imagine that it would even be nicer\n> >> for such an empty exec to behave as if it were \"exec false\" but with\n> >> less severe error message, i.e. a way for the user to say \"I want to\n> >> break the sequence here and get an interactive session\".  We may not\n> >> even need to add the \"break\" insn if we go that way and there is one\n> >> less thing for users to learn.  I dunno, but I tend to prefer giving\n> >> a useful and safe behaviour to interactive users other than erroring\n> >> out, when there _is_ such a safe behaviour that is obvious from the\n> >> situation, and I feel that an empty \"exec\" is such a case.\n> > \n> > That would make things unnecessarily confusing. An empty command is not\n> > `false` with a gentler error message. An empty command is a missing\n> > command.\n> \n> I agree that having a special meaning to the empty command would be\n> confusing. Also giving it on the command line only helps if you want to\n> stop after each pick and my impression is that people want to break\n> after specific commits to amend a fixup or something like that.\n> \n> > I am, however, concerned that special-casing an empty command will not\n> > make things better: if the user called `git rebase --exec=fasle`, they\n> > will *still* have to clean up their edit script.\n> \n> The empty commands create an invalid todo list which git cannot parse,\n> this patch is not a step down the path of checking that the command\n> exists or is valid shell - I don't think that would be possible in the\n> general case.\n\nWell, at least the error message is helpful: it suggests --edit-todo.\n\nBut as I said in another reply, I understand now that your patch validates\nthe argument as necessary to produce a valid todo list.\n\nThanks,\nDscho\n\n> \n> Best Wishes\n> \n> Phillip\n> \n> > Or just `git rebase --abort`, which I would do whether I had forgotten to\n> > specify a command or whether I had a typo in my command.\n> > \n> >>> Also check that the command does not contain any newlines as the\n> >>> todo-list format is unable to cope with multiline commands. Note that\n> >>> this changes the behavior, before this change one could do\n> >>>\n> >>> git rebase --exec='echo one\n> >>> exec echo two'\n> >>\n> >> It is very good to check the input, regardless of what an empty\n> >> \"exec\" should do.\n> > \n> > Should we then also check for incorrect quoting, missing commands, other\n> > errors? I am not sure that this path leads to sanity.\n> > \n> > Ciao,\n> > Dscho\n> > \n> \n> \n"},{"id":"368029","messageId":"20190129184327.30391-1-phillip.wood@talktalk.net","threadId":"50341","inReplyTo":"nycvar.QRO.7.76.6.1901291632070.41@tvgsbejvaqbjf.bet","subject":"[PATCH v2] rebase -x: sanity check command","fromName":"Phillip Wood","fromEmail":"phillip.wood@talktalk.net","sentAt":"2019-01-29T18:43:27Z","receivedAt":"2019-01-29T18:43:29Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Phillip Wood <phillip.wood@dunelm.org.uk>\n\nIf the user gives an empty argument to --exec then git creates a todo\nlist that it cannot parse. The rebase starts to run before erroring out\nwith\n\n  error: missing arguments for exec\n  error: invalid line 2: exec\n  You can fix this with 'git rebase --edit-todo' and then run 'git rebase --continue'.\n  Or you can abort the rebase with 'git rebase --abort'.\n\nInstead check for empty commands before starting the rebase.\n\nAlso check that the command does not contain any newlines as the\ntodo-list format is unable to cope with multiline commands. Note that\nthis changes the behavior, before this change one could do\n\ngit rebase --exec='echo one\nexec echo two'\n\nand it would insert two exec lines in the todo list, now it will error\nout.\n\nSigned-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n---\n\nApologies for the resend but I messed up the from address on the\nprevious send and I don't think it made it to the mailing list.\n\nThanks for the comments. I've updated the code as suggested by Dscho\nand tried to make it clearer in the commit message that this is fixing\ngit creating a todo-list that it cannot parse.\n\nRange-diff against v1:\n1:  9626549aec ! 1:  726b84c300 rebase -x: sanity check command\n    @@ -2,8 +2,9 @@\n     \n         rebase -x: sanity check command\n     \n    -    If the user gives an empty argument to --exec then the rebase starts to\n    -    run before erroring out with\n    +    If the user gives an empty argument to --exec then git creates a todo\n    +    list that it cannot parse. The rebase starts to run before erroring out\n    +    with\n     \n           error: missing arguments for exec\n           error: invalid line 2: exec\n    @@ -33,21 +34,16 @@\n      \n     +static int check_exec_cmd(const char *cmd)\n     +{\n    -+\tint non_blank = 0;\n    ++\tif (strchr(cmd, '\\n'))\n    ++\t\treturn error(_(\"exec commands cannot contain newlines\"));\n     +\n    -+\twhile (*cmd) {\n    -+\t\tif (*cmd == '\\n')\n    -+\t\t\treturn error(_(\"exec commands cannot contain newlines\"));\n    -+\t\tif (!isspace(*cmd))\n    -+\t\t\tnon_blank = 1;\n    -+\t\tcmd++;\n    -+\t}\n    ++\t/* Does the command consist purely of whitespace? */\n    ++\tif (!cmd[strspn(cmd, \" \\t\\r\\f\\v\")])\n    ++\t\treturn error(_(\"empty exec command\"));\n     +\n    -+\tif (non_blank)\n    -+\t\treturn 0;\n    -+\n    -+\treturn error(_(\"empty exec command\"));\n    ++\treturn 0;\n     +}\n    ++\n     +\n      int cmd_rebase(int argc, const char **argv, const char *prefix)\n      {\n\n builtin/rebase.c              | 17 +++++++++++++++++\n t/t3404-rebase-interactive.sh | 19 +++++++++++++++++++\n 2 files changed, 36 insertions(+)\n\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 00de70365e..f75bd79b45 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -793,6 +793,19 @@ static void set_reflog_action(struct rebase_options *options)\n \tstrbuf_release(&buf);\n }\n \n+static int check_exec_cmd(const char *cmd)\n+{\n+\tif (strchr(cmd, '\\n'))\n+\t\treturn error(_(\"exec commands cannot contain newlines\"));\n+\n+\t/* Does the command consist purely of whitespace? */\n+\tif (!cmd[strspn(cmd, \" \\t\\r\\f\\v\")])\n+\t\treturn error(_(\"empty exec command\"));\n+\n+\treturn 0;\n+}\n+\n+\n int cmd_rebase(int argc, const char **argv, const char *prefix)\n {\n \tstruct rebase_options options = {\n@@ -1130,6 +1143,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\t}\n \t}\n \n+\tfor (i = 0; i < exec.nr; i++)\n+\t\tif (check_exec_cmd(exec.items[i].string))\n+\t\t\texit(1);\n+\n \tif (!(options.flags & REBASE_NO_QUIET))\n \t\targv_array_push(&options.git_am_opts, \"-q\");\n \ndiff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\nindex 7a440e08d8..c98f64eb2d 100755\n--- a/t/t3404-rebase-interactive.sh\n+++ b/t/t3404-rebase-interactive.sh\n@@ -147,6 +147,25 @@ test_expect_success 'rebase -i with the exec command checks tree cleanness' '\n \tgit rebase --continue\n '\n \n+test_expect_success 'rebase -x with empty command fails' '\n+\ttest_when_finished \"git rebase --abort ||:\" &&\n+\ttest_must_fail git rebase -x \"\" @ 2>actual &&\n+\ttest_write_lines \"error: empty exec command\" >expected &&\n+\ttest_i18ncmp expected actual &&\n+\ttest_must_fail git rebase -x \" \" @ 2>actual &&\n+\ttest_i18ncmp expected actual\n+'\n+\n+LF='\n+'\n+test_expect_success 'rebase -x with newline in command fails' '\n+\ttest_when_finished \"git rebase --abort ||:\" &&\n+\ttest_must_fail git rebase -x \"a${LF}b\" @ 2>actual &&\n+\ttest_write_lines \"error: exec commands cannot contain newlines\" \\\n+\t\t\t >expected &&\n+\ttest_i18ncmp expected actual\n+'\n+\n test_expect_success 'rebase -i with exec of inexistent command' '\n \tgit checkout master &&\n \ttest_when_finished \"git rebase --abort\" &&\n-- \n2.20.1\n\n"},{"id":"368052","messageId":"xmqqk1in6sh3.fsf@gitster-ct.c.googlers.com","threadId":"50341","inReplyTo":"20190129184327.30391-1-phillip.wood@talktalk.net","subject":"Re: [PATCH v2] rebase -x: sanity check command","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-01-29T21:53:28Z","receivedAt":"2019-01-29T21:53:37Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Phillip Wood <phillip.wood@talktalk.net> writes:\n\n> Thanks for the comments. I've updated the code as suggested by Dscho\n> and tried to make it clearer in the commit message that this is fixing\n> git creating a todo-list that it cannot parse.\n\nWill queue.  Thanks.\n"},{"id":"368122","messageId":"nycvar.QRO.7.76.6.1901301325370.41@tvgsbejvaqbjf.bet","threadId":"50341","inReplyTo":"20190129184327.30391-1-phillip.wood@talktalk.net","subject":"Re: [PATCH v2] rebase -x: sanity check command","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2019-01-30T12:25:53Z","receivedAt":"2019-01-30T12:26:19Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Phillip,\n\nOn Tue, 29 Jan 2019, Phillip Wood wrote:\n\n> Range-diff against v1:\n> 1:  9626549aec ! 1:  726b84c300 rebase -x: sanity check command\n>     @@ -2,8 +2,9 @@\n>      \n>          rebase -x: sanity check command\n>      \n>     -    If the user gives an empty argument to --exec then the rebase starts to\n>     -    run before erroring out with\n>     +    If the user gives an empty argument to --exec then git creates a todo\n>     +    list that it cannot parse. The rebase starts to run before erroring out\n>     +    with\n>      \n>            error: missing arguments for exec\n>            error: invalid line 2: exec\n>     @@ -33,21 +34,16 @@\n>       \n>      +static int check_exec_cmd(const char *cmd)\n>      +{\n>     -+\tint non_blank = 0;\n>     ++\tif (strchr(cmd, '\\n'))\n>     ++\t\treturn error(_(\"exec commands cannot contain newlines\"));\n>      +\n>     -+\twhile (*cmd) {\n>     -+\t\tif (*cmd == '\\n')\n>     -+\t\t\treturn error(_(\"exec commands cannot contain newlines\"));\n>     -+\t\tif (!isspace(*cmd))\n>     -+\t\t\tnon_blank = 1;\n>     -+\t\tcmd++;\n>     -+\t}\n>     ++\t/* Does the command consist purely of whitespace? */\n>     ++\tif (!cmd[strspn(cmd, \" \\t\\r\\f\\v\")])\n>     ++\t\treturn error(_(\"empty exec command\"));\n>      +\n>     -+\tif (non_blank)\n>     -+\t\treturn 0;\n>     -+\n>     -+\treturn error(_(\"empty exec command\"));\n>     ++\treturn 0;\n>      +}\n>     ++\n>      +\n>       int cmd_rebase(int argc, const char **argv, const char *prefix)\n>       {\n\nLooks great!\n\nThanks,\nDscho\n"},{"id":"369232","messageId":"87ftsrke6r.fsf@evledraar.gmail.com","threadId":"50341","inReplyTo":"20190129184327.30391-1-phillip.wood@talktalk.net","subject":"Re: [PATCH v2] rebase -x: sanity check command","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2019-02-13T13:31:24Z","receivedAt":"2019-02-13T13:31:37Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Tue, Jan 29 2019, Phillip Wood wrote:\n\n> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n>\n> If the user gives an empty argument to --exec then git creates a todo\n> list that it cannot parse. The rebase starts to run before erroring out\n> with\n>\n>   error: missing arguments for exec\n>   error: invalid line 2: exec\n>   You can fix this with 'git rebase --edit-todo' and then run 'git rebase --continue'.\n>   Or you can abort the rebase with 'git rebase --abort'.\n>\n> Instead check for empty commands before starting the rebase.\n>\n> Also check that the command does not contain any newlines as the\n> todo-list format is unable to cope with multiline commands. Note that\n> this changes the behavior, before this change one could do\n>\n> git rebase --exec='echo one\n> exec echo two'\n>\n> and it would insert two exec lines in the todo list, now it will error\n> out.\n>\n> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n> ---\n>\n> Apologies for the resend but I messed up the from address on the\n> previous send and I don't think it made it to the mailing list.\n>\n> Thanks for the comments. I've updated the code as suggested by Dscho\n> and tried to make it clearer in the commit message that this is fixing\n> git creating a todo-list that it cannot parse.\n>\n> Range-diff against v1:\n> 1:  9626549aec ! 1:  726b84c300 rebase -x: sanity check command\n>     @@ -2,8 +2,9 @@\n>\n>          rebase -x: sanity check command\n>\n>     -    If the user gives an empty argument to --exec then the rebase starts to\n>     -    run before erroring out with\n>     +    If the user gives an empty argument to --exec then git creates a todo\n>     +    list that it cannot parse. The rebase starts to run before erroring out\n>     +    with\n>\n>            error: missing arguments for exec\n>            error: invalid line 2: exec\n>     @@ -33,21 +34,16 @@\n>\n>      +static int check_exec_cmd(const char *cmd)\n>      +{\n>     -+\tint non_blank = 0;\n>     ++\tif (strchr(cmd, '\\n'))\n>     ++\t\treturn error(_(\"exec commands cannot contain newlines\"));\n>      +\n>     -+\twhile (*cmd) {\n>     -+\t\tif (*cmd == '\\n')\n>     -+\t\t\treturn error(_(\"exec commands cannot contain newlines\"));\n>     -+\t\tif (!isspace(*cmd))\n>     -+\t\t\tnon_blank = 1;\n>     -+\t\tcmd++;\n>     -+\t}\n>     ++\t/* Does the command consist purely of whitespace? */\n>     ++\tif (!cmd[strspn(cmd, \" \\t\\r\\f\\v\")])\n>     ++\t\treturn error(_(\"empty exec command\"));\n>      +\n>     -+\tif (non_blank)\n>     -+\t\treturn 0;\n>     -+\n>     -+\treturn error(_(\"empty exec command\"));\n>     ++\treturn 0;\n>      +}\n>     ++\n>      +\n>       int cmd_rebase(int argc, const char **argv, const char *prefix)\n>       {\n>\n>  builtin/rebase.c              | 17 +++++++++++++++++\n>  t/t3404-rebase-interactive.sh | 19 +++++++++++++++++++\n>  2 files changed, 36 insertions(+)\n>\n> diff --git a/builtin/rebase.c b/builtin/rebase.c\n> index 00de70365e..f75bd79b45 100644\n> --- a/builtin/rebase.c\n> +++ b/builtin/rebase.c\n> @@ -793,6 +793,19 @@ static void set_reflog_action(struct rebase_options *options)\n>  \tstrbuf_release(&buf);\n>  }\n>\n> +static int check_exec_cmd(const char *cmd)\n> +{\n> +\tif (strchr(cmd, '\\n'))\n> +\t\treturn error(_(\"exec commands cannot contain newlines\"));\n> +\n> +\t/* Does the command consist purely of whitespace? */\n> +\tif (!cmd[strspn(cmd, \" \\t\\r\\f\\v\")])\n> +\t\treturn error(_(\"empty exec command\"));\n> +\n> +\treturn 0;\n> +}\n> +\n> +\n>  int cmd_rebase(int argc, const char **argv, const char *prefix)\n>  {\n>  \tstruct rebase_options options = {\n> @@ -1130,6 +1143,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>  \t\t}\n>  \t}\n>\n> +\tfor (i = 0; i < exec.nr; i++)\n> +\t\tif (check_exec_cmd(exec.items[i].string))\n> +\t\t\texit(1);\n> +\n>  \tif (!(options.flags & REBASE_NO_QUIET))\n>  \t\targv_array_push(&options.git_am_opts, \"-q\");\n>\n> diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\n> index 7a440e08d8..c98f64eb2d 100755\n> --- a/t/t3404-rebase-interactive.sh\n> +++ b/t/t3404-rebase-interactive.sh\n> @@ -147,6 +147,25 @@ test_expect_success 'rebase -i with the exec command checks tree cleanness' '\n>  \tgit rebase --continue\n>  '\n>\n> +test_expect_success 'rebase -x with empty command fails' '\n> +\ttest_when_finished \"git rebase --abort ||:\" &&\n> +\ttest_must_fail git rebase -x \"\" @ 2>actual &&\n> +\ttest_write_lines \"error: empty exec command\" >expected &&\n> +\ttest_i18ncmp expected actual &&\n> +\ttest_must_fail git rebase -x \" \" @ 2>actual &&\n> +\ttest_i18ncmp expected actual\n> +'\n> +\n> +LF='\n> +'\n> +test_expect_success 'rebase -x with newline in command fails' '\n> +\ttest_when_finished \"git rebase --abort ||:\" &&\n> +\ttest_must_fail git rebase -x \"a${LF}b\" @ 2>actual &&\n> +\ttest_write_lines \"error: exec commands cannot contain newlines\" \\\n> +\t\t\t >expected &&\n> +\ttest_i18ncmp expected actual\n> +'\n> +\n>  test_expect_success 'rebase -i with exec of inexistent command' '\n>  \tgit checkout master &&\n>  \ttest_when_finished \"git rebase --abort\" &&\n\nThis patch breaks the test suite (with these two new tests) under\nGIT_TEST_REBASE_USE_BUILTIN=false. So a 2.21.0-rc0 regression.\n\nIt would have been better to raise this before the rc period, but I just\nnoticed this now, but we can now:\n\n 1. Skip the test under that mode\n 2. Fix the shell code to do the same thing\n 3. Just remove the shell code & GIT_TEST_REBASE_USE_BUILTIN=false mode\n\nMaybe we should just do #3. The reason for the escape hatch was in case\nwe had bugs, and now we've had a full release cycle, but maybe that's\ntoo early...\n"},{"id":"369234","messageId":"20190213142209.8226-1-avarab@gmail.com","threadId":"50341","inReplyTo":"87ftsrke6r.fsf@evledraar.gmail.com","subject":"[PATCH] rebase: remove the rebase.useBuiltin setting","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2019-02-13T14:22:09Z","receivedAt":"2019-02-13T14:22:28Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Remove the rebase.useBuiltin setting, which was added as an escape\nhatch to disable the builtin version of rebase first released with Git\n2.20.\n\nSee [1] for the initial implementation of rebase.useBuiltin, and [2]\nand [3] for the documentation and corresponding\nGIT_TEST_REBASE_USE_BUILTIN option.\n\nAs noted in [4] the test suite hasn't passed with\nGIT_TEST_REBASE_USE_BUILTIN=false since c762aada1a (\"rebase -x: sanity\ncheck command\", 2019-01-29). We could fix this as we did for another\nsuch bug in 7e097e27d3 (\"legacy-rebase: backport -C<n> and\n--whitespace=<option> checks\", 2018-11-20), or just decide that the\nbuilt-in version is stable enough, and remove the legacy version. This\npatch implements that removal of the legacy version.\n\n1. 55071ea248 (\"rebase: start implementing it as a builtin\",\n   2018-08-07)\n2. d8d0a546f0 (\"rebase doc: document rebase.useBuiltin\", 2018-11-14)\n3. 62c23938fa (\"tests: add a special setup where rebase.useBuiltin is\n   off\", 2018-11-14)\n4. https://public-inbox.org/git/87ftsrke6r.fsf@evledraar.gmail.com/\n---\n\nOn Wed, Feb 13 2019, Ævar Arnfjörð Bjarmason wrote:\n> On Tue, Jan 29 2019, Phillip Wood wrote:\n>> [...]\n>>  test_expect_success 'rebase -i with exec of inexistent command' '\n>>      git checkout master &&\n>>      test_when_finished \"git rebase --abort\" &&\n>\n> This patch breaks the test suite (with these two new tests) under\n> GIT_TEST_REBASE_USE_BUILTIN=false. So a 2.21.0-rc0 regression.\n>\n> It would have been better to raise this before the rc period, but I just\n> noticed this now, but we can now:\n>\n>  1. Skip the test under that mode\n>  2. Fix the shell code to do the same thing\n>  3. Just remove the shell code & GIT_TEST_REBASE_USE_BUILTIN=false mode\n>\n> Maybe we should just do #3. The reason for the escape hatch was in case\n> we had bugs, and now we've had a full release cycle, but maybe that's\n> too early...\n\nHere is approach #3, intended for 2.21, but I'll defer to Junio on\nwhether we should take that approach.\n\n Documentation/config/rebase.txt |  17 +-\n Makefile                        |   1 -\n builtin/rebase.c                |  17 +-\n git-legacy-rebase.sh            | 770 --------------------------------\n t/README                        |   4 -\n t/t3400-rebase.sh               |   6 +\n 6 files changed, 13 insertions(+), 802 deletions(-)\n delete mode 100755 git-legacy-rebase.sh\n\ndiff --git a/Documentation/config/rebase.txt b/Documentation/config/rebase.txt\nindex 331d250e04..c747452983 100644\n--- a/Documentation/config/rebase.txt\n+++ b/Documentation/config/rebase.txt\n@@ -1,16 +1,9 @@\n rebase.useBuiltin::\n-\tSet to `false` to use the legacy shellscript implementation of\n-\tlinkgit:git-rebase[1]. Is `true` by default, which means use\n-\tthe built-in rewrite of it in C.\n-+\n-The C rewrite is first included with Git version 2.20. This option\n-serves an an escape hatch to re-enable the legacy version in case any\n-bugs are found in the rewrite. This option and the shellscript version\n-of linkgit:git-rebase[1] will be removed in some future release.\n-+\n-If you find some reason to set this option to `false` other than\n-one-off testing you should report the behavior difference as a bug in\n-git.\n+\tUnused configuration variable. Used between Git version 2.20\n+\tand 2.21 as an escape hatch to enable the legacy shellscript\n+\timplementation of rebase. Now the built-in rewrite of it in C\n+\tis always used. Setting this will emit a warning, to alert any\n+\tremaining users that setting this now does nothing.\n \n rebase.stat::\n \tWhether to show a diffstat of what changed upstream since the last\ndiff --git a/Makefile b/Makefile\nindex 0e13a5b469..58dceccd8a 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -626,7 +626,6 @@ SCRIPT_SH += git-merge-one-file.sh\n SCRIPT_SH += git-merge-resolve.sh\n SCRIPT_SH += git-mergetool.sh\n SCRIPT_SH += git-quiltimport.sh\n-SCRIPT_SH += git-legacy-rebase.sh\n SCRIPT_SH += git-remote-testgit.sh\n SCRIPT_SH += git-request-pull.sh\n SCRIPT_SH += git-stash.sh\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 7c7bc13e91..37a036933d 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -1135,21 +1135,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t};\n \tint i;\n \n-\t/*\n-\t * NEEDSWORK: Once the builtin rebase has been tested enough\n-\t * and git-legacy-rebase.sh is retired to contrib/, this preamble\n-\t * can be removed.\n-\t */\n-\n-\tif (!use_builtin_rebase()) {\n-\t\tconst char *path = mkpath(\"%s/git-legacy-rebase\",\n-\t\t\t\t\t  git_exec_path());\n-\n-\t\tif (sane_execvp(path, (char **)argv) < 0)\n-\t\t\tdie_errno(_(\"could not exec %s\"), path);\n-\t\telse\n-\t\t\tBUG(\"sane_execvp() returned???\");\n-\t}\n+\tif (!use_builtin_rebase())\n+\t\twarning(_(\"The rebase.useBuiltin support has been removed!\"));\n \n \tif (argc == 2 && !strcmp(argv[1], \"-h\"))\n \t\tusage_with_options(builtin_rebase_usage,\ndiff --git a/git-legacy-rebase.sh b/git-legacy-rebase.sh\ndeleted file mode 100755\nindex 5c2c4e5276..0000000000\n--- a/git-legacy-rebase.sh\n+++ /dev/null\n@@ -1,770 +0,0 @@\n-#!/bin/sh\n-#\n-# Copyright (c) 2005 Junio C Hamano.\n-#\n-\n-SUBDIRECTORY_OK=Yes\n-OPTIONS_KEEPDASHDASH=\n-OPTIONS_STUCKLONG=t\n-OPTIONS_SPEC=\"\\\n-git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] [<upstream>] [<branch>]\n-git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] --root [<branch>]\n-git rebase --continue | --abort | --skip | --edit-todo\n---\n- Available options are\n-v,verbose!         display a diffstat of what changed upstream\n-q,quiet!           be quiet. implies --no-stat\n-autostash          automatically stash/stash pop before and after\n-fork-point         use 'merge-base --fork-point' to refine upstream\n-onto=!             rebase onto given branch instead of upstream\n-r,rebase-merges?   try to rebase merges instead of skipping them\n-p,preserve-merges! try to recreate merges instead of ignoring them\n-s,strategy=!       use the given merge strategy\n-X,strategy-option=! pass the argument through to the merge strategy\n-no-ff!             cherry-pick all commits, even if unchanged\n-f,force-rebase!    cherry-pick all commits, even if unchanged\n-m,merge!           use merging strategies to rebase\n-i,interactive!     let the user edit the list of commits to rebase\n-x,exec=!           add exec lines after each commit of the editable list\n-k,keep-empty\t   preserve empty commits during rebase\n-allow-empty-message allow rebasing commits with empty messages\n-stat!              display a diffstat of what changed upstream\n-n,no-stat!         do not show diffstat of what changed upstream\n-verify             allow pre-rebase hook to run\n-rerere-autoupdate  allow rerere to update index with resolved conflicts\n-root!              rebase all reachable commits up to the root(s)\n-autosquash         move commits that begin with squash!/fixup! under -i\n-signoff            add a Signed-off-by: line to each commit\n-committer-date-is-author-date! passed to 'git am'\n-ignore-date!       passed to 'git am'\n-whitespace=!       passed to 'git apply'\n-ignore-whitespace! passed to 'git apply'\n-C=!                passed to 'git apply'\n-S,gpg-sign?        GPG-sign commits\n- Actions:\n-continue!          continue\n-abort!             abort and check out the original branch\n-skip!              skip current patch and continue\n-edit-todo!         edit the todo list during an interactive rebase\n-quit!              abort but keep HEAD where it is\n-show-current-patch! show the patch file being applied or merged\n-reschedule-failed-exec automatically reschedule failed exec commands\n-\"\n-. git-sh-setup\n-set_reflog_action rebase\n-require_work_tree_exists\n-cd_to_toplevel\n-\n-LF='\n-'\n-ok_to_skip_pre_rebase=\n-\n-squash_onto=\n-unset onto\n-unset restrict_revision\n-cmd=\n-strategy=\n-strategy_opts=\n-do_merge=\n-merge_dir=\"$GIT_DIR\"/rebase-merge\n-apply_dir=\"$GIT_DIR\"/rebase-apply\n-verbose=\n-diffstat=\n-test \"$(git config --bool rebase.stat)\" = true && diffstat=t\n-autostash=\"$(git config --bool rebase.autostash || echo false)\"\n-fork_point=auto\n-git_am_opt=\n-git_format_patch_opt=\n-rebase_root=\n-force_rebase=\n-allow_rerere_autoupdate=\n-# Non-empty if a rebase was in progress when 'git rebase' was invoked\n-in_progress=\n-# One of {am, merge, interactive}\n-type=\n-# One of {\"$GIT_DIR\"/rebase-apply, \"$GIT_DIR\"/rebase-merge}\n-state_dir=\n-# One of {'', continue, skip, abort}, as parsed from command line\n-action=\n-rebase_merges=\n-rebase_cousins=\n-preserve_merges=\n-autosquash=\n-keep_empty=\n-allow_empty_message=--allow-empty-message\n-signoff=\n-reschedule_failed_exec=\n-test \"$(git config --bool rebase.autosquash)\" = \"true\" && autosquash=t\n-case \"$(git config --bool commit.gpgsign)\" in\n-true)\tgpg_sign_opt=-S ;;\n-*)\tgpg_sign_opt= ;;\n-esac\n-test \"$(git config --bool rebase.reschedulefailedexec)\" = \"true\" &&\n-reschedule_failed_exec=--reschedule-failed-exec\n-. git-rebase--common\n-\n-read_basic_state () {\n-\ttest -f \"$state_dir/head-name\" &&\n-\ttest -f \"$state_dir/onto\" &&\n-\thead_name=$(cat \"$state_dir\"/head-name) &&\n-\tonto=$(cat \"$state_dir\"/onto) &&\n-\t# We always write to orig-head, but interactive rebase used to write to\n-\t# head. Fall back to reading from head to cover for the case that the\n-\t# user upgraded git with an ongoing interactive rebase.\n-\tif test -f \"$state_dir\"/orig-head\n-\tthen\n-\t\torig_head=$(cat \"$state_dir\"/orig-head)\n-\telse\n-\t\torig_head=$(cat \"$state_dir\"/head)\n-\tfi &&\n-\ttest -f \"$state_dir\"/quiet && GIT_QUIET=t\n-\ttest -f \"$state_dir\"/verbose && verbose=t\n-\ttest -f \"$state_dir\"/strategy && strategy=\"$(cat \"$state_dir\"/strategy)\"\n-\ttest -f \"$state_dir\"/strategy_opts &&\n-\t\tstrategy_opts=\"$(cat \"$state_dir\"/strategy_opts)\"\n-\ttest -f \"$state_dir\"/allow_rerere_autoupdate &&\n-\t\tallow_rerere_autoupdate=\"$(cat \"$state_dir\"/allow_rerere_autoupdate)\"\n-\ttest -f \"$state_dir\"/gpg_sign_opt &&\n-\t\tgpg_sign_opt=\"$(cat \"$state_dir\"/gpg_sign_opt)\"\n-\ttest -f \"$state_dir\"/signoff && {\n-\t\tsignoff=\"$(cat \"$state_dir\"/signoff)\"\n-\t\tforce_rebase=t\n-\t}\n-\ttest -f \"$state_dir\"/reschedule-failed-exec &&\n-\t\treschedule_failed_exec=t\n-}\n-\n-finish_rebase () {\n-\trm -f \"$(git rev-parse --git-path REBASE_HEAD)\"\n-\tapply_autostash &&\n-\t{ git gc --auto || true; } &&\n-\trm -rf \"$state_dir\"\n-}\n-\n-run_interactive () {\n-\tGIT_CHERRY_PICK_HELP=\"$resolvemsg\"\n-\texport GIT_CHERRY_PICK_HELP\n-\n-\ttest -n \"$keep_empty\" && keep_empty=\"--keep-empty\"\n-\ttest -n \"$rebase_merges\" && rebase_merges=\"--rebase-merges\"\n-\ttest -n \"$rebase_cousins\" && rebase_cousins=\"--rebase-cousins\"\n-\ttest -n \"$autosquash\" && autosquash=\"--autosquash\"\n-\ttest -n \"$verbose\" && verbose=\"--verbose\"\n-\ttest -n \"$force_rebase\" && force_rebase=\"--no-ff\"\n-\ttest -n \"$restrict_revision\" && \\\n-\t\trestrict_revision=\"--restrict-revision=^$restrict_revision\"\n-\ttest -n \"$upstream\" && upstream=\"--upstream=$upstream\"\n-\ttest -n \"$onto\" && onto=\"--onto=$onto\"\n-\ttest -n \"$squash_onto\" && squash_onto=\"--squash-onto=$squash_onto\"\n-\ttest -n \"$onto_name\" && onto_name=\"--onto-name=$onto_name\"\n-\ttest -n \"$head_name\" && head_name=\"--head-name=$head_name\"\n-\ttest -n \"$strategy\" && strategy=\"--strategy=$strategy\"\n-\ttest -n \"$strategy_opts\" && strategy_opts=\"--strategy-opts=$strategy_opts\"\n-\ttest -n \"$switch_to\" && switch_to=\"--switch-to=$switch_to\"\n-\ttest -n \"$cmd\" && cmd=\"--cmd=$cmd\"\n-\ttest -n \"$action\" && action=\"--$action\"\n-\n-\texec git rebase--interactive \"$action\" \"$keep_empty\" \"$rebase_merges\" \"$rebase_cousins\" \\\n-\t\t\"$upstream\" \"$onto\" \"$squash_onto\" \"$restrict_revision\" \\\n-\t\t\"$allow_empty_message\" \"$autosquash\" \"$verbose\" \\\n-\t\t\"$force_rebase\" \"$onto_name\" \"$head_name\" \"$strategy\" \\\n-\t\t\"$strategy_opts\" \"$cmd\" \"$switch_to\" \\\n-\t\t\"$allow_rerere_autoupdate\" \"$gpg_sign_opt\" \"$signoff\" \\\n-\t\t\"$reschedule_failed_exec\"\n-}\n-\n-run_specific_rebase () {\n-\tif [ \"$interactive_rebase\" = implied ]; then\n-\t\tGIT_SEQUENCE_EDITOR=:\n-\t\texport GIT_SEQUENCE_EDITOR\n-\t\tautosquash=\n-\tfi\n-\n-\tif test -n \"$interactive_rebase\" -a -z \"$preserve_merges\"\n-\tthen\n-\t\trun_interactive\n-\telse\n-\t\t. git-rebase--$type\n-\n-\t\tif test -z \"$preserve_merges\"\n-\t\tthen\n-\t\t\tgit_rebase__$type\n-\t\telse\n-\t\t\tgit_rebase__preserve_merges\n-\t\tfi\n-\tfi\n-\n-\tret=$?\n-\tif test $ret -eq 0\n-\tthen\n-\t\tfinish_rebase\n-\telif test $ret -eq 2 # special exit status for rebase -p\n-\tthen\n-\t\tapply_autostash &&\n-\t\trm -rf \"$state_dir\" &&\n-\t\tdie \"Nothing to do\"\n-\tfi\n-\texit $ret\n-}\n-\n-run_pre_rebase_hook () {\n-\tif test -z \"$ok_to_skip_pre_rebase\" &&\n-\t   test -x \"$(git rev-parse --git-path hooks/pre-rebase)\"\n-\tthen\n-\t\t\"$(git rev-parse --git-path hooks/pre-rebase)\" ${1+\"$@\"} ||\n-\t\tdie \"$(gettext \"The pre-rebase hook refused to rebase.\")\"\n-\tfi\n-}\n-\n-test -f \"$apply_dir\"/applying &&\n-\tdie \"$(gettext \"It looks like 'git am' is in progress. Cannot rebase.\")\"\n-\n-if test -d \"$apply_dir\"\n-then\n-\ttype=am\n-\tstate_dir=\"$apply_dir\"\n-elif test -d \"$merge_dir\"\n-then\n-\ttype=interactive\n-\tif test -d \"$merge_dir\"/rewritten\n-\tthen\n-\t\ttype=preserve-merges\n-\t\tinteractive_rebase=explicit\n-\t\tpreserve_merges=t\n-\telif test -f \"$merge_dir\"/interactive\n-\tthen\n-\t\tinteractive_rebase=explicit\n-\tfi\n-\tstate_dir=\"$merge_dir\"\n-fi\n-test -n \"$type\" && in_progress=t\n-\n-total_argc=$#\n-while test $# != 0\n-do\n-\tcase \"$1\" in\n-\t--no-verify)\n-\t\tok_to_skip_pre_rebase=yes\n-\t\t;;\n-\t--verify)\n-\t\tok_to_skip_pre_rebase=\n-\t\t;;\n-\t--continue|--skip|--abort|--quit|--edit-todo|--show-current-patch)\n-\t\ttest $total_argc -eq 2 || usage\n-\t\taction=${1##--}\n-\t\t;;\n-\t--onto=*)\n-\t\tonto=\"${1#--onto=}\"\n-\t\t;;\n-\t--exec=*)\n-\t\tcmd=\"${cmd}exec ${1#--exec=}${LF}\"\n-\t\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n-\t\t;;\n-\t--interactive)\n-\t\tinteractive_rebase=explicit\n-\t\t;;\n-\t--keep-empty)\n-\t\tkeep_empty=yes\n-\t\t;;\n-\t--allow-empty-message)\n-\t\tallow_empty_message=--allow-empty-message\n-\t\t;;\n-\t--no-keep-empty)\n-\t\tkeep_empty=\n-\t\t;;\n-\t--rebase-merges)\n-\t\trebase_merges=t\n-\t\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n-\t\t;;\n-\t--rebase-merges=*)\n-\t\trebase_merges=t\n-\t\tcase \"${1#*=}\" in\n-\t\trebase-cousins) rebase_cousins=t;;\n-\t\tno-rebase-cousins) rebase_cousins=;;\n-\t\t*) die \"Unknown mode: $1\";;\n-\t\tesac\n-\t\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n-\t\t;;\n-\t--preserve-merges)\n-\t\tpreserve_merges=t\n-\t\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n-\t\t;;\n-\t--autosquash)\n-\t\tautosquash=t\n-\t\t;;\n-\t--no-autosquash)\n-\t\tautosquash=\n-\t\t;;\n-\t--fork-point)\n-\t\tfork_point=t\n-\t\t;;\n-\t--no-fork-point)\n-\t\tfork_point=\n-\t\t;;\n-\t--merge)\n-\t\tdo_merge=t\n-\t\t;;\n-\t--strategy-option=*)\n-\t\tstrategy_opts=\"$strategy_opts $(git rev-parse --sq-quote \"--${1#--strategy-option=}\" | sed -e s/^.//)\"\n-\t\tdo_merge=t\n-\t\ttest -z \"$strategy\" && strategy=recursive\n-\t\t;;\n-\t--strategy=*)\n-\t\tstrategy=\"${1#--strategy=}\"\n-\t\tdo_merge=t\n-\t\t;;\n-\t--no-stat)\n-\t\tdiffstat=\n-\t\t;;\n-\t--stat)\n-\t\tdiffstat=t\n-\t\t;;\n-\t--autostash)\n-\t\tautostash=true\n-\t\t;;\n-\t--no-autostash)\n-\t\tautostash=false\n-\t\t;;\n-\t--verbose)\n-\t\tverbose=t\n-\t\tdiffstat=t\n-\t\tGIT_QUIET=\n-\t\t;;\n-\t--quiet)\n-\t\tGIT_QUIET=t\n-\t\tgit_am_opt=\"$git_am_opt -q\"\n-\t\tverbose=\n-\t\tdiffstat=\n-\t\t;;\n-\t--whitespace=*)\n-\t\tgit_am_opt=\"$git_am_opt --whitespace=${1#--whitespace=}\"\n-\t\tcase \"${1#--whitespace=}\" in\n-\t\tfix|strip)\n-\t\t\tforce_rebase=t\n-\t\t\t;;\n-\t\twarn|nowarn|error|error-all)\n-\t\t\t;; # okay, known whitespace option\n-\t\t*)\n-\t\t\tdie \"fatal: Invalid whitespace option: '${1#*=}'\"\n-\t\t\t;;\n-\t\tesac\n-\t\t;;\n-\t--ignore-whitespace)\n-\t\tgit_am_opt=\"$git_am_opt $1\"\n-\t\t;;\n-\t--signoff)\n-\t\tsignoff=--signoff\n-\t\t;;\n-\t--no-signoff)\n-\t\tsignoff=\n-\t\t;;\n-\t--committer-date-is-author-date|--ignore-date)\n-\t\tgit_am_opt=\"$git_am_opt $1\"\n-\t\tforce_rebase=t\n-\t\t;;\n-\t-C*[!0-9]*)\n-\t\tdie \"fatal: switch \\`C' expects a numerical value\"\n-\t\t;;\n-\t-C*)\n-\t\tgit_am_opt=\"$git_am_opt $1\"\n-\t\t;;\n-\t--root)\n-\t\trebase_root=t\n-\t\t;;\n-\t--force-rebase|--no-ff)\n-\t\tforce_rebase=t\n-\t\t;;\n-\t--rerere-autoupdate|--no-rerere-autoupdate)\n-\t\tallow_rerere_autoupdate=\"$1\"\n-\t\t;;\n-\t--gpg-sign)\n-\t\tgpg_sign_opt=-S\n-\t\t;;\n-\t--gpg-sign=*)\n-\t\tgpg_sign_opt=\"-S${1#--gpg-sign=}\"\n-\t\t;;\n-\t--reschedule-failed-exec)\n-\t\treschedule_failed_exec=--reschedule-failed-exec\n-\t\t;;\n-\t--no-reschedule-failed-exec)\n-\t\treschedule_failed_exec=\n-\t\t;;\n-\t--)\n-\t\tshift\n-\t\tbreak\n-\t\t;;\n-\t*)\n-\t\tusage\n-\t\t;;\n-\tesac\n-\tshift\n-done\n-test $# -gt 2 && usage\n-\n-if test -n \"$action\"\n-then\n-\ttest -z \"$in_progress\" && die \"$(gettext \"No rebase in progress?\")\"\n-\t# Only interactive rebase uses detailed reflog messages\n-\tif test -n \"$interactive_rebase\" && test \"$GIT_REFLOG_ACTION\" = rebase\n-\tthen\n-\t\tGIT_REFLOG_ACTION=\"rebase -i ($action)\"\n-\t\texport GIT_REFLOG_ACTION\n-\tfi\n-fi\n-\n-if test \"$action\" = \"edit-todo\" && test -z \"$interactive_rebase\"\n-then\n-\tdie \"$(gettext \"The --edit-todo action can only be used during interactive rebase.\")\"\n-fi\n-\n-case \"$action\" in\n-continue)\n-\t# Sanity check\n-\tgit rev-parse --verify HEAD >/dev/null ||\n-\t\tdie \"$(gettext \"Cannot read HEAD\")\"\n-\tgit update-index --ignore-submodules --refresh &&\n-\tgit diff-files --quiet --ignore-submodules || {\n-\t\techo \"$(gettext \"You must edit all merge conflicts and then\n-mark them as resolved using git add\")\"\n-\t\texit 1\n-\t}\n-\tread_basic_state\n-\trun_specific_rebase\n-\t;;\n-skip)\n-\toutput git reset --hard HEAD || exit $?\n-\tread_basic_state\n-\trun_specific_rebase\n-\t;;\n-abort)\n-\tgit rerere clear\n-\tread_basic_state\n-\tcase \"$head_name\" in\n-\trefs/*)\n-\t\tgit symbolic-ref -m \"rebase: aborting\" HEAD $head_name ||\n-\t\tdie \"$(eval_gettext \"Could not move back to \\$head_name\")\"\n-\t\t;;\n-\tesac\n-\toutput git reset --hard $orig_head\n-\tfinish_rebase\n-\texit\n-\t;;\n-quit)\n-\texec rm -rf \"$state_dir\"\n-\t;;\n-edit-todo)\n-\trun_specific_rebase\n-\t;;\n-show-current-patch)\n-\trun_specific_rebase\n-\tdie \"BUG: run_specific_rebase is not supposed to return here\"\n-\t;;\n-esac\n-\n-# Make sure no rebase is in progress\n-if test -n \"$in_progress\"\n-then\n-\tstate_dir_base=${state_dir##*/}\n-\tcmd_live_rebase=\"git rebase (--continue | --abort | --skip)\"\n-\tcmd_clear_stale_rebase=\"rm -fr \\\"$state_dir\\\"\"\n-\tdie \"\n-$(eval_gettext 'It seems that there is already a $state_dir_base directory, and\n-I wonder if you are in the middle of another rebase.  If that is the\n-case, please try\n-\t$cmd_live_rebase\n-If that is not the case, please\n-\t$cmd_clear_stale_rebase\n-and run me again.  I am stopping in case you still have something\n-valuable there.')\"\n-fi\n-\n-if test -n \"$rebase_root\" && test -z \"$onto\"\n-then\n-\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n-fi\n-\n-if test -n \"$keep_empty\"\n-then\n-\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n-fi\n-\n-actually_interactive=\n-if test -n \"$interactive_rebase\"\n-then\n-\tif test -z \"$preserve_merges\"\n-\tthen\n-\t\ttype=interactive\n-\telse\n-\t\ttype=preserve-merges\n-\tfi\n-\tactually_interactive=t\n-\tstate_dir=\"$merge_dir\"\n-elif test -n \"$do_merge\"\n-then\n-\tinteractive_rebase=implied\n-\ttype=interactive\n-\tstate_dir=\"$merge_dir\"\n-else\n-\ttype=am\n-\tstate_dir=\"$apply_dir\"\n-fi\n-\n-if test -t 2 && test -z \"$GIT_QUIET\"\n-then\n-\tgit_format_patch_opt=\"$git_format_patch_opt --progress\"\n-fi\n-\n-incompatible_opts=$(echo \" $git_am_opt \" | \\\n-\t\t    sed -e 's/ -q / /g' -e 's/^ \\(.*\\) $/\\1/')\n-if test -n \"$incompatible_opts\"\n-then\n-\tif test -n \"$actually_interactive\" || test \"$do_merge\"\n-\tthen\n-\t\tdie \"$(gettext \"fatal: cannot combine am options with either interactive or merge options\")\"\n-\tfi\n-fi\n-\n-if test -n \"$signoff\"\n-then\n-\ttest -n \"$preserve_merges\" &&\n-\t\tdie \"$(gettext \"fatal: cannot combine '--signoff' with '--preserve-merges'\")\"\n-\tgit_am_opt=\"$git_am_opt $signoff\"\n-\tforce_rebase=t\n-fi\n-\n-if test -n \"$preserve_merges\"\n-then\n-\t# Note: incompatibility with --signoff handled in signoff block above\n-\t# Note: incompatibility with --interactive is just a strong warning;\n-\t#       git-rebase.txt caveats with \"unless you know what you are doing\"\n-\ttest -n \"$rebase_merges\" &&\n-\t\tdie \"$(gettext \"fatal: cannot combine '--preserve-merges' with '--rebase-merges'\")\"\n-\n-\ttest -n \"$reschedule_failed_exec\" &&\n-\t\tdie \"$(gettext \"error: cannot combine '--preserve-merges' with '--reschedule-failed-exec'\")\"\n-fi\n-\n-if test -n \"$rebase_merges\"\n-then\n-\ttest -n \"$strategy_opts\" &&\n-\t\tdie \"$(gettext \"fatal: cannot combine '--rebase-merges' with '--strategy-option'\")\"\n-\ttest -n \"$strategy\" &&\n-\t\tdie \"$(gettext \"fatal: cannot combine '--rebase-merges' with '--strategy'\")\"\n-fi\n-\n-if test -z \"$rebase_root\"\n-then\n-\tcase \"$#\" in\n-\t0)\n-\t\tif ! upstream_name=$(git rev-parse --symbolic-full-name \\\n-\t\t\t--verify -q @{upstream} 2>/dev/null)\n-\t\tthen\n-\t\t\t. git-parse-remote\n-\t\t\terror_on_missing_default_upstream \"rebase\" \"rebase\" \\\n-\t\t\t\t\"against\" \"git rebase $(gettext '<branch>')\"\n-\t\tfi\n-\n-\t\ttest \"$fork_point\" = auto && fork_point=t\n-\t\t;;\n-\t*)\tupstream_name=\"$1\"\n-\t\tif test \"$upstream_name\" = \"-\"\n-\t\tthen\n-\t\t\tupstream_name=\"@{-1}\"\n-\t\tfi\n-\t\tshift\n-\t\t;;\n-\tesac\n-\tupstream=$(peel_committish \"${upstream_name}\") ||\n-\tdie \"$(eval_gettext \"invalid upstream '\\$upstream_name'\")\"\n-\tupstream_arg=\"$upstream_name\"\n-else\n-\tif test -z \"$onto\"\n-\tthen\n-\t\tempty_tree=$(git hash-object -t tree /dev/null)\n-\t\tonto=$(git commit-tree $empty_tree </dev/null)\n-\t\tsquash_onto=\"$onto\"\n-\tfi\n-\tunset upstream_name\n-\tunset upstream\n-\ttest $# -gt 1 && usage\n-\tupstream_arg=--root\n-fi\n-\n-# Make sure the branch to rebase onto is valid.\n-onto_name=${onto-\"$upstream_name\"}\n-case \"$onto_name\" in\n-*...*)\n-\tif\tleft=${onto_name%...*} right=${onto_name#*...} &&\n-\t\tonto=$(git merge-base --all ${left:-HEAD} ${right:-HEAD})\n-\tthen\n-\t\tcase \"$onto\" in\n-\t\t?*\"$LF\"?*)\n-\t\t\tdie \"$(eval_gettext \"\\$onto_name: there are more than one merge bases\")\"\n-\t\t\t;;\n-\t\t'')\n-\t\t\tdie \"$(eval_gettext \"\\$onto_name: there is no merge base\")\"\n-\t\t\t;;\n-\t\tesac\n-\telse\n-\t\tdie \"$(eval_gettext \"\\$onto_name: there is no merge base\")\"\n-\tfi\n-\t;;\n-*)\n-\tonto=$(peel_committish \"$onto_name\") ||\n-\tdie \"$(eval_gettext \"Does not point to a valid commit: \\$onto_name\")\"\n-\t;;\n-esac\n-\n-# If the branch to rebase is given, that is the branch we will rebase\n-# $branch_name -- branch/commit being rebased, or HEAD (already detached)\n-# $orig_head -- commit object name of tip of the branch before rebasing\n-# $head_name -- refs/heads/<that-branch> or \"detached HEAD\"\n-switch_to=\n-case \"$#\" in\n-1)\n-\t# Is it \"rebase other $branchname\" or \"rebase other $commit\"?\n-\tbranch_name=\"$1\"\n-\tswitch_to=\"$1\"\n-\n-\t# Is it a local branch?\n-\tif git show-ref --verify --quiet -- \"refs/heads/$branch_name\" &&\n-\t   orig_head=$(git rev-parse -q --verify \"refs/heads/$branch_name\")\n-\tthen\n-\t\thead_name=\"refs/heads/$branch_name\"\n-\t# If not is it a valid ref (branch or commit)?\n-\telif orig_head=$(git rev-parse -q --verify \"$branch_name\")\n-\tthen\n-\t\thead_name=\"detached HEAD\"\n-\n-\telse\n-\t\tdie \"$(eval_gettext \"fatal: no such branch/commit '\\$branch_name'\")\"\n-\tfi\n-\t;;\n-0)\n-\t# Do not need to switch branches, we are already on it.\n-\tif branch_name=$(git symbolic-ref -q HEAD)\n-\tthen\n-\t\thead_name=$branch_name\n-\t\tbranch_name=$(expr \"z$branch_name\" : 'zrefs/heads/\\(.*\\)')\n-\telse\n-\t\thead_name=\"detached HEAD\"\n-\t\tbranch_name=HEAD\n-\tfi\n-\torig_head=$(git rev-parse --verify HEAD) || exit\n-\t;;\n-*)\n-\tdie \"BUG: unexpected number of arguments left to parse\"\n-\t;;\n-esac\n-\n-if test \"$fork_point\" = t\n-then\n-\tnew_upstream=$(git merge-base --fork-point \"$upstream_name\" \\\n-\t\t\t\"${switch_to:-HEAD}\")\n-\tif test -n \"$new_upstream\"\n-\tthen\n-\t\trestrict_revision=$new_upstream\n-\tfi\n-fi\n-\n-if test \"$autostash\" = true && ! (require_clean_work_tree) 2>/dev/null\n-then\n-\tstash_sha1=$(git stash create \"autostash\") ||\n-\tdie \"$(gettext 'Cannot autostash')\"\n-\n-\tmkdir -p \"$state_dir\" &&\n-\techo $stash_sha1 >\"$state_dir/autostash\" &&\n-\tstash_abbrev=$(git rev-parse --short $stash_sha1) &&\n-\techo \"$(eval_gettext 'Created autostash: $stash_abbrev')\" &&\n-\tgit reset --hard\n-fi\n-\n-require_clean_work_tree \"rebase\" \"$(gettext \"Please commit or stash them.\")\"\n-\n-# Now we are rebasing commits $upstream..$orig_head (or with --root,\n-# everything leading up to $orig_head) on top of $onto\n-\n-# Check if we are already based on $onto with linear history,\n-# but this should be done only when upstream and onto are the same\n-# and if this is not an interactive rebase.\n-mb=$(git merge-base \"$onto\" \"$orig_head\")\n-if test -z \"$actually_interactive\" && test \"$upstream\" = \"$onto\" &&\n-\ttest \"$mb\" = \"$onto\" && test -z \"$restrict_revision\" &&\n-\t# linear history?\n-\t! (git rev-list --parents \"$onto\"..\"$orig_head\" | sane_grep \" .* \") > /dev/null\n-then\n-\tif test -z \"$force_rebase\"\n-\tthen\n-\t\t# Lazily switch to the target branch if needed...\n-\t\ttest -z \"$switch_to\" ||\n-\t\tGIT_REFLOG_ACTION=\"$GIT_REFLOG_ACTION: checkout $switch_to\" \\\n-\t\t\tgit checkout -q \"$switch_to\" --\n-\t\tif test \"$branch_name\" = \"HEAD\" &&\n-\t\t\t ! git symbolic-ref -q HEAD\n-\t\tthen\n-\t\t\tsay \"$(eval_gettext \"HEAD is up to date.\")\"\n-\t\telse\n-\t\t\tsay \"$(eval_gettext \"Current branch \\$branch_name is up to date.\")\"\n-\t\tfi\n-\t\tfinish_rebase\n-\t\texit 0\n-\telse\n-\t\tif test \"$branch_name\" = \"HEAD\" &&\n-\t\t\t ! git symbolic-ref -q HEAD\n-\t\tthen\n-\t\t\tsay \"$(eval_gettext \"HEAD is up to date, rebase forced.\")\"\n-\t\telse\n-\t\t\tsay \"$(eval_gettext \"Current branch \\$branch_name is up to date, rebase forced.\")\"\n-\t\tfi\n-\tfi\n-fi\n-\n-# If a hook exists, give it a chance to interrupt\n-run_pre_rebase_hook \"$upstream_arg\" \"$@\"\n-\n-if test -n \"$diffstat\"\n-then\n-\tif test -n \"$verbose\"\n-\tthen\n-\t\tif test -z \"$mb\"\n-\t\tthen\n-\t\t\techo \"$(eval_gettext \"Changes to \\$onto:\")\"\n-\t\telse\n-\t\t\techo \"$(eval_gettext \"Changes from \\$mb to \\$onto:\")\"\n-\t\tfi\n-\tfi\n-\tmb_tree=\"${mb:-$(git hash-object -t tree /dev/null)}\"\n-\t# We want color (if set), but no pager\n-\tGIT_PAGER='' git diff --stat --summary \"$mb_tree\" \"$onto\"\n-fi\n-\n-if test -z \"$actually_interactive\" && test \"$mb\" = \"$orig_head\"\n-then\n-\tsay \"$(eval_gettext \"Fast-forwarded \\$branch_name to \\$onto_name.\")\"\n-\tGIT_REFLOG_ACTION=\"$GIT_REFLOG_ACTION: checkout $onto_name\" \\\n-\t\tgit checkout -q \"$onto^0\" || die \"could not detach HEAD\"\n-\t# If the $onto is a proper descendant of the tip of the branch, then\n-\t# we just fast-forwarded.\n-\tgit update-ref ORIG_HEAD $orig_head\n-\tmove_to_original_branch\n-\tfinish_rebase\n-\texit 0\n-fi\n-\n-test -n \"$interactive_rebase\" && run_specific_rebase\n-\n-# Detach HEAD and reset the tree\n-say \"$(gettext \"First, rewinding head to replay your work on top of it...\")\"\n-\n-GIT_REFLOG_ACTION=\"$GIT_REFLOG_ACTION: checkout $onto_name\" \\\n-\tgit checkout -q \"$onto^0\" || die \"could not detach HEAD\"\n-git update-ref ORIG_HEAD $orig_head\n-\n-if test -n \"$rebase_root\"\n-then\n-\trevisions=\"$onto..$orig_head\"\n-else\n-\trevisions=\"${restrict_revision-$upstream}..$orig_head\"\n-fi\n-\n-run_specific_rebase\ndiff --git a/t/README b/t/README\nindex 1326fd7505..decceb8576 100644\n--- a/t/README\n+++ b/t/README\n@@ -374,10 +374,6 @@ the --no-sparse command-line argument.\n GIT_TEST_PRELOAD_INDEX=<boolean> exercises the preload-index code path\n by overriding the minimum number of cache entries required per thread.\n \n-GIT_TEST_REBASE_USE_BUILTIN=<boolean>, when false, disables the\n-builtin version of git-rebase. See 'rebase.useBuiltin' in\n-git-config(1).\n-\n GIT_TEST_INDEX_THREADS=<n> enables exercising the multi-threaded loading\n of the index for the whole test suite by bypassing the default number of\n cache entries and thread minimums. Setting this to 1 will make the\ndiff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh\nindex 3e73f7584c..0a88eed1db 100755\n--- a/t/t3400-rebase.sh\n+++ b/t/t3400-rebase.sh\n@@ -311,4 +311,10 @@ test_expect_success 'rebase--merge.sh and --show-current-patch' '\n \t)\n '\n \n+test_expect_success 'rebase -c rebase.useBuiltin=false warning' '\n+\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN= \\\n+\t\tgit -c rebase.useBuiltin=false rebase 2>err &&\n+\ttest_i18ngrep \"rebase.useBuiltin support has been removed\" err\n+'\n+\n test_done\n-- \n2.20.1.611.gfbb209baf1\n\n"},{"id":"369237","messageId":"nycvar.QRO.7.76.6.1902131724570.41@tvgsbejvaqbjf.bet","threadId":"50341","inReplyTo":"20190213142209.8226-1-avarab@gmail.com","subject":"Re: [PATCH] rebase: remove the rebase.useBuiltin setting","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2019-02-13T16:25:10Z","receivedAt":"2019-02-13T16:25:42Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Ævar,\n\nOn Wed, 13 Feb 2019, Ævar Arnfjörð Bjarmason wrote:\n\n> Remove the rebase.useBuiltin setting, which was added as an escape\n> hatch to disable the builtin version of rebase first released with Git\n> 2.20.\n\nI like it!\n\nThanks,\nDscho\n\n> \n> See [1] for the initial implementation of rebase.useBuiltin, and [2]\n> and [3] for the documentation and corresponding\n> GIT_TEST_REBASE_USE_BUILTIN option.\n> \n> As noted in [4] the test suite hasn't passed with\n> GIT_TEST_REBASE_USE_BUILTIN=false since c762aada1a (\"rebase -x: sanity\n> check command\", 2019-01-29). We could fix this as we did for another\n> such bug in 7e097e27d3 (\"legacy-rebase: backport -C<n> and\n> --whitespace=<option> checks\", 2018-11-20), or just decide that the\n> built-in version is stable enough, and remove the legacy version. This\n> patch implements that removal of the legacy version.\n> \n> 1. 55071ea248 (\"rebase: start implementing it as a builtin\",\n>    2018-08-07)\n> 2. d8d0a546f0 (\"rebase doc: document rebase.useBuiltin\", 2018-11-14)\n> 3. 62c23938fa (\"tests: add a special setup where rebase.useBuiltin is\n>    off\", 2018-11-14)\n> 4. https://public-inbox.org/git/87ftsrke6r.fsf@evledraar.gmail.com/\n> ---\n> \n> On Wed, Feb 13 2019, Ævar Arnfjörð Bjarmason wrote:\n> > On Tue, Jan 29 2019, Phillip Wood wrote:\n> >> [...]\n> >>  test_expect_success 'rebase -i with exec of inexistent command' '\n> >>      git checkout master &&\n> >>      test_when_finished \"git rebase --abort\" &&\n> >\n> > This patch breaks the test suite (with these two new tests) under\n> > GIT_TEST_REBASE_USE_BUILTIN=false. So a 2.21.0-rc0 regression.\n> >\n> > It would have been better to raise this before the rc period, but I just\n> > noticed this now, but we can now:\n> >\n> >  1. Skip the test under that mode\n> >  2. Fix the shell code to do the same thing\n> >  3. Just remove the shell code & GIT_TEST_REBASE_USE_BUILTIN=false mode\n> >\n> > Maybe we should just do #3. The reason for the escape hatch was in case\n> > we had bugs, and now we've had a full release cycle, but maybe that's\n> > too early...\n> \n> Here is approach #3, intended for 2.21, but I'll defer to Junio on\n> whether we should take that approach.\n> \n>  Documentation/config/rebase.txt |  17 +-\n>  Makefile                        |   1 -\n>  builtin/rebase.c                |  17 +-\n>  git-legacy-rebase.sh            | 770 --------------------------------\n>  t/README                        |   4 -\n>  t/t3400-rebase.sh               |   6 +\n>  6 files changed, 13 insertions(+), 802 deletions(-)\n>  delete mode 100755 git-legacy-rebase.sh\n> \n> diff --git a/Documentation/config/rebase.txt b/Documentation/config/rebase.txt\n> index 331d250e04..c747452983 100644\n> --- a/Documentation/config/rebase.txt\n> +++ b/Documentation/config/rebase.txt\n> @@ -1,16 +1,9 @@\n>  rebase.useBuiltin::\n> -\tSet to `false` to use the legacy shellscript implementation of\n> -\tlinkgit:git-rebase[1]. Is `true` by default, which means use\n> -\tthe built-in rewrite of it in C.\n> -+\n> -The C rewrite is first included with Git version 2.20. This option\n> -serves an an escape hatch to re-enable the legacy version in case any\n> -bugs are found in the rewrite. This option and the shellscript version\n> -of linkgit:git-rebase[1] will be removed in some future release.\n> -+\n> -If you find some reason to set this option to `false` other than\n> -one-off testing you should report the behavior difference as a bug in\n> -git.\n> +\tUnused configuration variable. Used between Git version 2.20\n> +\tand 2.21 as an escape hatch to enable the legacy shellscript\n> +\timplementation of rebase. Now the built-in rewrite of it in C\n> +\tis always used. Setting this will emit a warning, to alert any\n> +\tremaining users that setting this now does nothing.\n>  \n>  rebase.stat::\n>  \tWhether to show a diffstat of what changed upstream since the last\n> diff --git a/Makefile b/Makefile\n> index 0e13a5b469..58dceccd8a 100644\n> --- a/Makefile\n> +++ b/Makefile\n> @@ -626,7 +626,6 @@ SCRIPT_SH += git-merge-one-file.sh\n>  SCRIPT_SH += git-merge-resolve.sh\n>  SCRIPT_SH += git-mergetool.sh\n>  SCRIPT_SH += git-quiltimport.sh\n> -SCRIPT_SH += git-legacy-rebase.sh\n>  SCRIPT_SH += git-remote-testgit.sh\n>  SCRIPT_SH += git-request-pull.sh\n>  SCRIPT_SH += git-stash.sh\n> diff --git a/builtin/rebase.c b/builtin/rebase.c\n> index 7c7bc13e91..37a036933d 100644\n> --- a/builtin/rebase.c\n> +++ b/builtin/rebase.c\n> @@ -1135,21 +1135,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>  \t};\n>  \tint i;\n>  \n> -\t/*\n> -\t * NEEDSWORK: Once the builtin rebase has been tested enough\n> -\t * and git-legacy-rebase.sh is retired to contrib/, this preamble\n> -\t * can be removed.\n> -\t */\n> -\n> -\tif (!use_builtin_rebase()) {\n> -\t\tconst char *path = mkpath(\"%s/git-legacy-rebase\",\n> -\t\t\t\t\t  git_exec_path());\n> -\n> -\t\tif (sane_execvp(path, (char **)argv) < 0)\n> -\t\t\tdie_errno(_(\"could not exec %s\"), path);\n> -\t\telse\n> -\t\t\tBUG(\"sane_execvp() returned???\");\n> -\t}\n> +\tif (!use_builtin_rebase())\n> +\t\twarning(_(\"The rebase.useBuiltin support has been removed!\"));\n>  \n>  \tif (argc == 2 && !strcmp(argv[1], \"-h\"))\n>  \t\tusage_with_options(builtin_rebase_usage,\n> diff --git a/git-legacy-rebase.sh b/git-legacy-rebase.sh\n> deleted file mode 100755\n> index 5c2c4e5276..0000000000\n> --- a/git-legacy-rebase.sh\n> +++ /dev/null\n> @@ -1,770 +0,0 @@\n> -#!/bin/sh\n> -#\n> -# Copyright (c) 2005 Junio C Hamano.\n> -#\n> -\n> -SUBDIRECTORY_OK=Yes\n> -OPTIONS_KEEPDASHDASH=\n> -OPTIONS_STUCKLONG=t\n> -OPTIONS_SPEC=\"\\\n> -git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] [<upstream>] [<branch>]\n> -git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] --root [<branch>]\n> -git rebase --continue | --abort | --skip | --edit-todo\n> ---\n> - Available options are\n> -v,verbose!         display a diffstat of what changed upstream\n> -q,quiet!           be quiet. implies --no-stat\n> -autostash          automatically stash/stash pop before and after\n> -fork-point         use 'merge-base --fork-point' to refine upstream\n> -onto=!             rebase onto given branch instead of upstream\n> -r,rebase-merges?   try to rebase merges instead of skipping them\n> -p,preserve-merges! try to recreate merges instead of ignoring them\n> -s,strategy=!       use the given merge strategy\n> -X,strategy-option=! pass the argument through to the merge strategy\n> -no-ff!             cherry-pick all commits, even if unchanged\n> -f,force-rebase!    cherry-pick all commits, even if unchanged\n> -m,merge!           use merging strategies to rebase\n> -i,interactive!     let the user edit the list of commits to rebase\n> -x,exec=!           add exec lines after each commit of the editable list\n> -k,keep-empty\t   preserve empty commits during rebase\n> -allow-empty-message allow rebasing commits with empty messages\n> -stat!              display a diffstat of what changed upstream\n> -n,no-stat!         do not show diffstat of what changed upstream\n> -verify             allow pre-rebase hook to run\n> -rerere-autoupdate  allow rerere to update index with resolved conflicts\n> -root!              rebase all reachable commits up to the root(s)\n> -autosquash         move commits that begin with squash!/fixup! under -i\n> -signoff            add a Signed-off-by: line to each commit\n> -committer-date-is-author-date! passed to 'git am'\n> -ignore-date!       passed to 'git am'\n> -whitespace=!       passed to 'git apply'\n> -ignore-whitespace! passed to 'git apply'\n> -C=!                passed to 'git apply'\n> -S,gpg-sign?        GPG-sign commits\n> - Actions:\n> -continue!          continue\n> -abort!             abort and check out the original branch\n> -skip!              skip current patch and continue\n> -edit-todo!         edit the todo list during an interactive rebase\n> -quit!              abort but keep HEAD where it is\n> -show-current-patch! show the patch file being applied or merged\n> -reschedule-failed-exec automatically reschedule failed exec commands\n> -\"\n> -. git-sh-setup\n> -set_reflog_action rebase\n> -require_work_tree_exists\n> -cd_to_toplevel\n> -\n> -LF='\n> -'\n> -ok_to_skip_pre_rebase=\n> -\n> -squash_onto=\n> -unset onto\n> -unset restrict_revision\n> -cmd=\n> -strategy=\n> -strategy_opts=\n> -do_merge=\n> -merge_dir=\"$GIT_DIR\"/rebase-merge\n> -apply_dir=\"$GIT_DIR\"/rebase-apply\n> -verbose=\n> -diffstat=\n> -test \"$(git config --bool rebase.stat)\" = true && diffstat=t\n> -autostash=\"$(git config --bool rebase.autostash || echo false)\"\n> -fork_point=auto\n> -git_am_opt=\n> -git_format_patch_opt=\n> -rebase_root=\n> -force_rebase=\n> -allow_rerere_autoupdate=\n> -# Non-empty if a rebase was in progress when 'git rebase' was invoked\n> -in_progress=\n> -# One of {am, merge, interactive}\n> -type=\n> -# One of {\"$GIT_DIR\"/rebase-apply, \"$GIT_DIR\"/rebase-merge}\n> -state_dir=\n> -# One of {'', continue, skip, abort}, as parsed from command line\n> -action=\n> -rebase_merges=\n> -rebase_cousins=\n> -preserve_merges=\n> -autosquash=\n> -keep_empty=\n> -allow_empty_message=--allow-empty-message\n> -signoff=\n> -reschedule_failed_exec=\n> -test \"$(git config --bool rebase.autosquash)\" = \"true\" && autosquash=t\n> -case \"$(git config --bool commit.gpgsign)\" in\n> -true)\tgpg_sign_opt=-S ;;\n> -*)\tgpg_sign_opt= ;;\n> -esac\n> -test \"$(git config --bool rebase.reschedulefailedexec)\" = \"true\" &&\n> -reschedule_failed_exec=--reschedule-failed-exec\n> -. git-rebase--common\n> -\n> -read_basic_state () {\n> -\ttest -f \"$state_dir/head-name\" &&\n> -\ttest -f \"$state_dir/onto\" &&\n> -\thead_name=$(cat \"$state_dir\"/head-name) &&\n> -\tonto=$(cat \"$state_dir\"/onto) &&\n> -\t# We always write to orig-head, but interactive rebase used to write to\n> -\t# head. Fall back to reading from head to cover for the case that the\n> -\t# user upgraded git with an ongoing interactive rebase.\n> -\tif test -f \"$state_dir\"/orig-head\n> -\tthen\n> -\t\torig_head=$(cat \"$state_dir\"/orig-head)\n> -\telse\n> -\t\torig_head=$(cat \"$state_dir\"/head)\n> -\tfi &&\n> -\ttest -f \"$state_dir\"/quiet && GIT_QUIET=t\n> -\ttest -f \"$state_dir\"/verbose && verbose=t\n> -\ttest -f \"$state_dir\"/strategy && strategy=\"$(cat \"$state_dir\"/strategy)\"\n> -\ttest -f \"$state_dir\"/strategy_opts &&\n> -\t\tstrategy_opts=\"$(cat \"$state_dir\"/strategy_opts)\"\n> -\ttest -f \"$state_dir\"/allow_rerere_autoupdate &&\n> -\t\tallow_rerere_autoupdate=\"$(cat \"$state_dir\"/allow_rerere_autoupdate)\"\n> -\ttest -f \"$state_dir\"/gpg_sign_opt &&\n> -\t\tgpg_sign_opt=\"$(cat \"$state_dir\"/gpg_sign_opt)\"\n> -\ttest -f \"$state_dir\"/signoff && {\n> -\t\tsignoff=\"$(cat \"$state_dir\"/signoff)\"\n> -\t\tforce_rebase=t\n> -\t}\n> -\ttest -f \"$state_dir\"/reschedule-failed-exec &&\n> -\t\treschedule_failed_exec=t\n> -}\n> -\n> -finish_rebase () {\n> -\trm -f \"$(git rev-parse --git-path REBASE_HEAD)\"\n> -\tapply_autostash &&\n> -\t{ git gc --auto || true; } &&\n> -\trm -rf \"$state_dir\"\n> -}\n> -\n> -run_interactive () {\n> -\tGIT_CHERRY_PICK_HELP=\"$resolvemsg\"\n> -\texport GIT_CHERRY_PICK_HELP\n> -\n> -\ttest -n \"$keep_empty\" && keep_empty=\"--keep-empty\"\n> -\ttest -n \"$rebase_merges\" && rebase_merges=\"--rebase-merges\"\n> -\ttest -n \"$rebase_cousins\" && rebase_cousins=\"--rebase-cousins\"\n> -\ttest -n \"$autosquash\" && autosquash=\"--autosquash\"\n> -\ttest -n \"$verbose\" && verbose=\"--verbose\"\n> -\ttest -n \"$force_rebase\" && force_rebase=\"--no-ff\"\n> -\ttest -n \"$restrict_revision\" && \\\n> -\t\trestrict_revision=\"--restrict-revision=^$restrict_revision\"\n> -\ttest -n \"$upstream\" && upstream=\"--upstream=$upstream\"\n> -\ttest -n \"$onto\" && onto=\"--onto=$onto\"\n> -\ttest -n \"$squash_onto\" && squash_onto=\"--squash-onto=$squash_onto\"\n> -\ttest -n \"$onto_name\" && onto_name=\"--onto-name=$onto_name\"\n> -\ttest -n \"$head_name\" && head_name=\"--head-name=$head_name\"\n> -\ttest -n \"$strategy\" && strategy=\"--strategy=$strategy\"\n> -\ttest -n \"$strategy_opts\" && strategy_opts=\"--strategy-opts=$strategy_opts\"\n> -\ttest -n \"$switch_to\" && switch_to=\"--switch-to=$switch_to\"\n> -\ttest -n \"$cmd\" && cmd=\"--cmd=$cmd\"\n> -\ttest -n \"$action\" && action=\"--$action\"\n> -\n> -\texec git rebase--interactive \"$action\" \"$keep_empty\" \"$rebase_merges\" \"$rebase_cousins\" \\\n> -\t\t\"$upstream\" \"$onto\" \"$squash_onto\" \"$restrict_revision\" \\\n> -\t\t\"$allow_empty_message\" \"$autosquash\" \"$verbose\" \\\n> -\t\t\"$force_rebase\" \"$onto_name\" \"$head_name\" \"$strategy\" \\\n> -\t\t\"$strategy_opts\" \"$cmd\" \"$switch_to\" \\\n> -\t\t\"$allow_rerere_autoupdate\" \"$gpg_sign_opt\" \"$signoff\" \\\n> -\t\t\"$reschedule_failed_exec\"\n> -}\n> -\n> -run_specific_rebase () {\n> -\tif [ \"$interactive_rebase\" = implied ]; then\n> -\t\tGIT_SEQUENCE_EDITOR=:\n> -\t\texport GIT_SEQUENCE_EDITOR\n> -\t\tautosquash=\n> -\tfi\n> -\n> -\tif test -n \"$interactive_rebase\" -a -z \"$preserve_merges\"\n> -\tthen\n> -\t\trun_interactive\n> -\telse\n> -\t\t. git-rebase--$type\n> -\n> -\t\tif test -z \"$preserve_merges\"\n> -\t\tthen\n> -\t\t\tgit_rebase__$type\n> -\t\telse\n> -\t\t\tgit_rebase__preserve_merges\n> -\t\tfi\n> -\tfi\n> -\n> -\tret=$?\n> -\tif test $ret -eq 0\n> -\tthen\n> -\t\tfinish_rebase\n> -\telif test $ret -eq 2 # special exit status for rebase -p\n> -\tthen\n> -\t\tapply_autostash &&\n> -\t\trm -rf \"$state_dir\" &&\n> -\t\tdie \"Nothing to do\"\n> -\tfi\n> -\texit $ret\n> -}\n> -\n> -run_pre_rebase_hook () {\n> -\tif test -z \"$ok_to_skip_pre_rebase\" &&\n> -\t   test -x \"$(git rev-parse --git-path hooks/pre-rebase)\"\n> -\tthen\n> -\t\t\"$(git rev-parse --git-path hooks/pre-rebase)\" ${1+\"$@\"} ||\n> -\t\tdie \"$(gettext \"The pre-rebase hook refused to rebase.\")\"\n> -\tfi\n> -}\n> -\n> -test -f \"$apply_dir\"/applying &&\n> -\tdie \"$(gettext \"It looks like 'git am' is in progress. Cannot rebase.\")\"\n> -\n> -if test -d \"$apply_dir\"\n> -then\n> -\ttype=am\n> -\tstate_dir=\"$apply_dir\"\n> -elif test -d \"$merge_dir\"\n> -then\n> -\ttype=interactive\n> -\tif test -d \"$merge_dir\"/rewritten\n> -\tthen\n> -\t\ttype=preserve-merges\n> -\t\tinteractive_rebase=explicit\n> -\t\tpreserve_merges=t\n> -\telif test -f \"$merge_dir\"/interactive\n> -\tthen\n> -\t\tinteractive_rebase=explicit\n> -\tfi\n> -\tstate_dir=\"$merge_dir\"\n> -fi\n> -test -n \"$type\" && in_progress=t\n> -\n> -total_argc=$#\n> -while test $# != 0\n> -do\n> -\tcase \"$1\" in\n> -\t--no-verify)\n> -\t\tok_to_skip_pre_rebase=yes\n> -\t\t;;\n> -\t--verify)\n> -\t\tok_to_skip_pre_rebase=\n> -\t\t;;\n> -\t--continue|--skip|--abort|--quit|--edit-todo|--show-current-patch)\n> -\t\ttest $total_argc -eq 2 || usage\n> -\t\taction=${1##--}\n> -\t\t;;\n> -\t--onto=*)\n> -\t\tonto=\"${1#--onto=}\"\n> -\t\t;;\n> -\t--exec=*)\n> -\t\tcmd=\"${cmd}exec ${1#--exec=}${LF}\"\n> -\t\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n> -\t\t;;\n> -\t--interactive)\n> -\t\tinteractive_rebase=explicit\n> -\t\t;;\n> -\t--keep-empty)\n> -\t\tkeep_empty=yes\n> -\t\t;;\n> -\t--allow-empty-message)\n> -\t\tallow_empty_message=--allow-empty-message\n> -\t\t;;\n> -\t--no-keep-empty)\n> -\t\tkeep_empty=\n> -\t\t;;\n> -\t--rebase-merges)\n> -\t\trebase_merges=t\n> -\t\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n> -\t\t;;\n> -\t--rebase-merges=*)\n> -\t\trebase_merges=t\n> -\t\tcase \"${1#*=}\" in\n> -\t\trebase-cousins) rebase_cousins=t;;\n> -\t\tno-rebase-cousins) rebase_cousins=;;\n> -\t\t*) die \"Unknown mode: $1\";;\n> -\t\tesac\n> -\t\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n> -\t\t;;\n> -\t--preserve-merges)\n> -\t\tpreserve_merges=t\n> -\t\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n> -\t\t;;\n> -\t--autosquash)\n> -\t\tautosquash=t\n> -\t\t;;\n> -\t--no-autosquash)\n> -\t\tautosquash=\n> -\t\t;;\n> -\t--fork-point)\n> -\t\tfork_point=t\n> -\t\t;;\n> -\t--no-fork-point)\n> -\t\tfork_point=\n> -\t\t;;\n> -\t--merge)\n> -\t\tdo_merge=t\n> -\t\t;;\n> -\t--strategy-option=*)\n> -\t\tstrategy_opts=\"$strategy_opts $(git rev-parse --sq-quote \"--${1#--strategy-option=}\" | sed -e s/^.//)\"\n> -\t\tdo_merge=t\n> -\t\ttest -z \"$strategy\" && strategy=recursive\n> -\t\t;;\n> -\t--strategy=*)\n> -\t\tstrategy=\"${1#--strategy=}\"\n> -\t\tdo_merge=t\n> -\t\t;;\n> -\t--no-stat)\n> -\t\tdiffstat=\n> -\t\t;;\n> -\t--stat)\n> -\t\tdiffstat=t\n> -\t\t;;\n> -\t--autostash)\n> -\t\tautostash=true\n> -\t\t;;\n> -\t--no-autostash)\n> -\t\tautostash=false\n> -\t\t;;\n> -\t--verbose)\n> -\t\tverbose=t\n> -\t\tdiffstat=t\n> -\t\tGIT_QUIET=\n> -\t\t;;\n> -\t--quiet)\n> -\t\tGIT_QUIET=t\n> -\t\tgit_am_opt=\"$git_am_opt -q\"\n> -\t\tverbose=\n> -\t\tdiffstat=\n> -\t\t;;\n> -\t--whitespace=*)\n> -\t\tgit_am_opt=\"$git_am_opt --whitespace=${1#--whitespace=}\"\n> -\t\tcase \"${1#--whitespace=}\" in\n> -\t\tfix|strip)\n> -\t\t\tforce_rebase=t\n> -\t\t\t;;\n> -\t\twarn|nowarn|error|error-all)\n> -\t\t\t;; # okay, known whitespace option\n> -\t\t*)\n> -\t\t\tdie \"fatal: Invalid whitespace option: '${1#*=}'\"\n> -\t\t\t;;\n> -\t\tesac\n> -\t\t;;\n> -\t--ignore-whitespace)\n> -\t\tgit_am_opt=\"$git_am_opt $1\"\n> -\t\t;;\n> -\t--signoff)\n> -\t\tsignoff=--signoff\n> -\t\t;;\n> -\t--no-signoff)\n> -\t\tsignoff=\n> -\t\t;;\n> -\t--committer-date-is-author-date|--ignore-date)\n> -\t\tgit_am_opt=\"$git_am_opt $1\"\n> -\t\tforce_rebase=t\n> -\t\t;;\n> -\t-C*[!0-9]*)\n> -\t\tdie \"fatal: switch \\`C' expects a numerical value\"\n> -\t\t;;\n> -\t-C*)\n> -\t\tgit_am_opt=\"$git_am_opt $1\"\n> -\t\t;;\n> -\t--root)\n> -\t\trebase_root=t\n> -\t\t;;\n> -\t--force-rebase|--no-ff)\n> -\t\tforce_rebase=t\n> -\t\t;;\n> -\t--rerere-autoupdate|--no-rerere-autoupdate)\n> -\t\tallow_rerere_autoupdate=\"$1\"\n> -\t\t;;\n> -\t--gpg-sign)\n> -\t\tgpg_sign_opt=-S\n> -\t\t;;\n> -\t--gpg-sign=*)\n> -\t\tgpg_sign_opt=\"-S${1#--gpg-sign=}\"\n> -\t\t;;\n> -\t--reschedule-failed-exec)\n> -\t\treschedule_failed_exec=--reschedule-failed-exec\n> -\t\t;;\n> -\t--no-reschedule-failed-exec)\n> -\t\treschedule_failed_exec=\n> -\t\t;;\n> -\t--)\n> -\t\tshift\n> -\t\tbreak\n> -\t\t;;\n> -\t*)\n> -\t\tusage\n> -\t\t;;\n> -\tesac\n> -\tshift\n> -done\n> -test $# -gt 2 && usage\n> -\n> -if test -n \"$action\"\n> -then\n> -\ttest -z \"$in_progress\" && die \"$(gettext \"No rebase in progress?\")\"\n> -\t# Only interactive rebase uses detailed reflog messages\n> -\tif test -n \"$interactive_rebase\" && test \"$GIT_REFLOG_ACTION\" = rebase\n> -\tthen\n> -\t\tGIT_REFLOG_ACTION=\"rebase -i ($action)\"\n> -\t\texport GIT_REFLOG_ACTION\n> -\tfi\n> -fi\n> -\n> -if test \"$action\" = \"edit-todo\" && test -z \"$interactive_rebase\"\n> -then\n> -\tdie \"$(gettext \"The --edit-todo action can only be used during interactive rebase.\")\"\n> -fi\n> -\n> -case \"$action\" in\n> -continue)\n> -\t# Sanity check\n> -\tgit rev-parse --verify HEAD >/dev/null ||\n> -\t\tdie \"$(gettext \"Cannot read HEAD\")\"\n> -\tgit update-index --ignore-submodules --refresh &&\n> -\tgit diff-files --quiet --ignore-submodules || {\n> -\t\techo \"$(gettext \"You must edit all merge conflicts and then\n> -mark them as resolved using git add\")\"\n> -\t\texit 1\n> -\t}\n> -\tread_basic_state\n> -\trun_specific_rebase\n> -\t;;\n> -skip)\n> -\toutput git reset --hard HEAD || exit $?\n> -\tread_basic_state\n> -\trun_specific_rebase\n> -\t;;\n> -abort)\n> -\tgit rerere clear\n> -\tread_basic_state\n> -\tcase \"$head_name\" in\n> -\trefs/*)\n> -\t\tgit symbolic-ref -m \"rebase: aborting\" HEAD $head_name ||\n> -\t\tdie \"$(eval_gettext \"Could not move back to \\$head_name\")\"\n> -\t\t;;\n> -\tesac\n> -\toutput git reset --hard $orig_head\n> -\tfinish_rebase\n> -\texit\n> -\t;;\n> -quit)\n> -\texec rm -rf \"$state_dir\"\n> -\t;;\n> -edit-todo)\n> -\trun_specific_rebase\n> -\t;;\n> -show-current-patch)\n> -\trun_specific_rebase\n> -\tdie \"BUG: run_specific_rebase is not supposed to return here\"\n> -\t;;\n> -esac\n> -\n> -# Make sure no rebase is in progress\n> -if test -n \"$in_progress\"\n> -then\n> -\tstate_dir_base=${state_dir##*/}\n> -\tcmd_live_rebase=\"git rebase (--continue | --abort | --skip)\"\n> -\tcmd_clear_stale_rebase=\"rm -fr \\\"$state_dir\\\"\"\n> -\tdie \"\n> -$(eval_gettext 'It seems that there is already a $state_dir_base directory, and\n> -I wonder if you are in the middle of another rebase.  If that is the\n> -case, please try\n> -\t$cmd_live_rebase\n> -If that is not the case, please\n> -\t$cmd_clear_stale_rebase\n> -and run me again.  I am stopping in case you still have something\n> -valuable there.')\"\n> -fi\n> -\n> -if test -n \"$rebase_root\" && test -z \"$onto\"\n> -then\n> -\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n> -fi\n> -\n> -if test -n \"$keep_empty\"\n> -then\n> -\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n> -fi\n> -\n> -actually_interactive=\n> -if test -n \"$interactive_rebase\"\n> -then\n> -\tif test -z \"$preserve_merges\"\n> -\tthen\n> -\t\ttype=interactive\n> -\telse\n> -\t\ttype=preserve-merges\n> -\tfi\n> -\tactually_interactive=t\n> -\tstate_dir=\"$merge_dir\"\n> -elif test -n \"$do_merge\"\n> -then\n> -\tinteractive_rebase=implied\n> -\ttype=interactive\n> -\tstate_dir=\"$merge_dir\"\n> -else\n> -\ttype=am\n> -\tstate_dir=\"$apply_dir\"\n> -fi\n> -\n> -if test -t 2 && test -z \"$GIT_QUIET\"\n> -then\n> -\tgit_format_patch_opt=\"$git_format_patch_opt --progress\"\n> -fi\n> -\n> -incompatible_opts=$(echo \" $git_am_opt \" | \\\n> -\t\t    sed -e 's/ -q / /g' -e 's/^ \\(.*\\) $/\\1/')\n> -if test -n \"$incompatible_opts\"\n> -then\n> -\tif test -n \"$actually_interactive\" || test \"$do_merge\"\n> -\tthen\n> -\t\tdie \"$(gettext \"fatal: cannot combine am options with either interactive or merge options\")\"\n> -\tfi\n> -fi\n> -\n> -if test -n \"$signoff\"\n> -then\n> -\ttest -n \"$preserve_merges\" &&\n> -\t\tdie \"$(gettext \"fatal: cannot combine '--signoff' with '--preserve-merges'\")\"\n> -\tgit_am_opt=\"$git_am_opt $signoff\"\n> -\tforce_rebase=t\n> -fi\n> -\n> -if test -n \"$preserve_merges\"\n> -then\n> -\t# Note: incompatibility with --signoff handled in signoff block above\n> -\t# Note: incompatibility with --interactive is just a strong warning;\n> -\t#       git-rebase.txt caveats with \"unless you know what you are doing\"\n> -\ttest -n \"$rebase_merges\" &&\n> -\t\tdie \"$(gettext \"fatal: cannot combine '--preserve-merges' with '--rebase-merges'\")\"\n> -\n> -\ttest -n \"$reschedule_failed_exec\" &&\n> -\t\tdie \"$(gettext \"error: cannot combine '--preserve-merges' with '--reschedule-failed-exec'\")\"\n> -fi\n> -\n> -if test -n \"$rebase_merges\"\n> -then\n> -\ttest -n \"$strategy_opts\" &&\n> -\t\tdie \"$(gettext \"fatal: cannot combine '--rebase-merges' with '--strategy-option'\")\"\n> -\ttest -n \"$strategy\" &&\n> -\t\tdie \"$(gettext \"fatal: cannot combine '--rebase-merges' with '--strategy'\")\"\n> -fi\n> -\n> -if test -z \"$rebase_root\"\n> -then\n> -\tcase \"$#\" in\n> -\t0)\n> -\t\tif ! upstream_name=$(git rev-parse --symbolic-full-name \\\n> -\t\t\t--verify -q @{upstream} 2>/dev/null)\n> -\t\tthen\n> -\t\t\t. git-parse-remote\n> -\t\t\terror_on_missing_default_upstream \"rebase\" \"rebase\" \\\n> -\t\t\t\t\"against\" \"git rebase $(gettext '<branch>')\"\n> -\t\tfi\n> -\n> -\t\ttest \"$fork_point\" = auto && fork_point=t\n> -\t\t;;\n> -\t*)\tupstream_name=\"$1\"\n> -\t\tif test \"$upstream_name\" = \"-\"\n> -\t\tthen\n> -\t\t\tupstream_name=\"@{-1}\"\n> -\t\tfi\n> -\t\tshift\n> -\t\t;;\n> -\tesac\n> -\tupstream=$(peel_committish \"${upstream_name}\") ||\n> -\tdie \"$(eval_gettext \"invalid upstream '\\$upstream_name'\")\"\n> -\tupstream_arg=\"$upstream_name\"\n> -else\n> -\tif test -z \"$onto\"\n> -\tthen\n> -\t\tempty_tree=$(git hash-object -t tree /dev/null)\n> -\t\tonto=$(git commit-tree $empty_tree </dev/null)\n> -\t\tsquash_onto=\"$onto\"\n> -\tfi\n> -\tunset upstream_name\n> -\tunset upstream\n> -\ttest $# -gt 1 && usage\n> -\tupstream_arg=--root\n> -fi\n> -\n> -# Make sure the branch to rebase onto is valid.\n> -onto_name=${onto-\"$upstream_name\"}\n> -case \"$onto_name\" in\n> -*...*)\n> -\tif\tleft=${onto_name%...*} right=${onto_name#*...} &&\n> -\t\tonto=$(git merge-base --all ${left:-HEAD} ${right:-HEAD})\n> -\tthen\n> -\t\tcase \"$onto\" in\n> -\t\t?*\"$LF\"?*)\n> -\t\t\tdie \"$(eval_gettext \"\\$onto_name: there are more than one merge bases\")\"\n> -\t\t\t;;\n> -\t\t'')\n> -\t\t\tdie \"$(eval_gettext \"\\$onto_name: there is no merge base\")\"\n> -\t\t\t;;\n> -\t\tesac\n> -\telse\n> -\t\tdie \"$(eval_gettext \"\\$onto_name: there is no merge base\")\"\n> -\tfi\n> -\t;;\n> -*)\n> -\tonto=$(peel_committish \"$onto_name\") ||\n> -\tdie \"$(eval_gettext \"Does not point to a valid commit: \\$onto_name\")\"\n> -\t;;\n> -esac\n> -\n> -# If the branch to rebase is given, that is the branch we will rebase\n> -# $branch_name -- branch/commit being rebased, or HEAD (already detached)\n> -# $orig_head -- commit object name of tip of the branch before rebasing\n> -# $head_name -- refs/heads/<that-branch> or \"detached HEAD\"\n> -switch_to=\n> -case \"$#\" in\n> -1)\n> -\t# Is it \"rebase other $branchname\" or \"rebase other $commit\"?\n> -\tbranch_name=\"$1\"\n> -\tswitch_to=\"$1\"\n> -\n> -\t# Is it a local branch?\n> -\tif git show-ref --verify --quiet -- \"refs/heads/$branch_name\" &&\n> -\t   orig_head=$(git rev-parse -q --verify \"refs/heads/$branch_name\")\n> -\tthen\n> -\t\thead_name=\"refs/heads/$branch_name\"\n> -\t# If not is it a valid ref (branch or commit)?\n> -\telif orig_head=$(git rev-parse -q --verify \"$branch_name\")\n> -\tthen\n> -\t\thead_name=\"detached HEAD\"\n> -\n> -\telse\n> -\t\tdie \"$(eval_gettext \"fatal: no such branch/commit '\\$branch_name'\")\"\n> -\tfi\n> -\t;;\n> -0)\n> -\t# Do not need to switch branches, we are already on it.\n> -\tif branch_name=$(git symbolic-ref -q HEAD)\n> -\tthen\n> -\t\thead_name=$branch_name\n> -\t\tbranch_name=$(expr \"z$branch_name\" : 'zrefs/heads/\\(.*\\)')\n> -\telse\n> -\t\thead_name=\"detached HEAD\"\n> -\t\tbranch_name=HEAD\n> -\tfi\n> -\torig_head=$(git rev-parse --verify HEAD) || exit\n> -\t;;\n> -*)\n> -\tdie \"BUG: unexpected number of arguments left to parse\"\n> -\t;;\n> -esac\n> -\n> -if test \"$fork_point\" = t\n> -then\n> -\tnew_upstream=$(git merge-base --fork-point \"$upstream_name\" \\\n> -\t\t\t\"${switch_to:-HEAD}\")\n> -\tif test -n \"$new_upstream\"\n> -\tthen\n> -\t\trestrict_revision=$new_upstream\n> -\tfi\n> -fi\n> -\n> -if test \"$autostash\" = true && ! (require_clean_work_tree) 2>/dev/null\n> -then\n> -\tstash_sha1=$(git stash create \"autostash\") ||\n> -\tdie \"$(gettext 'Cannot autostash')\"\n> -\n> -\tmkdir -p \"$state_dir\" &&\n> -\techo $stash_sha1 >\"$state_dir/autostash\" &&\n> -\tstash_abbrev=$(git rev-parse --short $stash_sha1) &&\n> -\techo \"$(eval_gettext 'Created autostash: $stash_abbrev')\" &&\n> -\tgit reset --hard\n> -fi\n> -\n> -require_clean_work_tree \"rebase\" \"$(gettext \"Please commit or stash them.\")\"\n> -\n> -# Now we are rebasing commits $upstream..$orig_head (or with --root,\n> -# everything leading up to $orig_head) on top of $onto\n> -\n> -# Check if we are already based on $onto with linear history,\n> -# but this should be done only when upstream and onto are the same\n> -# and if this is not an interactive rebase.\n> -mb=$(git merge-base \"$onto\" \"$orig_head\")\n> -if test -z \"$actually_interactive\" && test \"$upstream\" = \"$onto\" &&\n> -\ttest \"$mb\" = \"$onto\" && test -z \"$restrict_revision\" &&\n> -\t# linear history?\n> -\t! (git rev-list --parents \"$onto\"..\"$orig_head\" | sane_grep \" .* \") > /dev/null\n> -then\n> -\tif test -z \"$force_rebase\"\n> -\tthen\n> -\t\t# Lazily switch to the target branch if needed...\n> -\t\ttest -z \"$switch_to\" ||\n> -\t\tGIT_REFLOG_ACTION=\"$GIT_REFLOG_ACTION: checkout $switch_to\" \\\n> -\t\t\tgit checkout -q \"$switch_to\" --\n> -\t\tif test \"$branch_name\" = \"HEAD\" &&\n> -\t\t\t ! git symbolic-ref -q HEAD\n> -\t\tthen\n> -\t\t\tsay \"$(eval_gettext \"HEAD is up to date.\")\"\n> -\t\telse\n> -\t\t\tsay \"$(eval_gettext \"Current branch \\$branch_name is up to date.\")\"\n> -\t\tfi\n> -\t\tfinish_rebase\n> -\t\texit 0\n> -\telse\n> -\t\tif test \"$branch_name\" = \"HEAD\" &&\n> -\t\t\t ! git symbolic-ref -q HEAD\n> -\t\tthen\n> -\t\t\tsay \"$(eval_gettext \"HEAD is up to date, rebase forced.\")\"\n> -\t\telse\n> -\t\t\tsay \"$(eval_gettext \"Current branch \\$branch_name is up to date, rebase forced.\")\"\n> -\t\tfi\n> -\tfi\n> -fi\n> -\n> -# If a hook exists, give it a chance to interrupt\n> -run_pre_rebase_hook \"$upstream_arg\" \"$@\"\n> -\n> -if test -n \"$diffstat\"\n> -then\n> -\tif test -n \"$verbose\"\n> -\tthen\n> -\t\tif test -z \"$mb\"\n> -\t\tthen\n> -\t\t\techo \"$(eval_gettext \"Changes to \\$onto:\")\"\n> -\t\telse\n> -\t\t\techo \"$(eval_gettext \"Changes from \\$mb to \\$onto:\")\"\n> -\t\tfi\n> -\tfi\n> -\tmb_tree=\"${mb:-$(git hash-object -t tree /dev/null)}\"\n> -\t# We want color (if set), but no pager\n> -\tGIT_PAGER='' git diff --stat --summary \"$mb_tree\" \"$onto\"\n> -fi\n> -\n> -if test -z \"$actually_interactive\" && test \"$mb\" = \"$orig_head\"\n> -then\n> -\tsay \"$(eval_gettext \"Fast-forwarded \\$branch_name to \\$onto_name.\")\"\n> -\tGIT_REFLOG_ACTION=\"$GIT_REFLOG_ACTION: checkout $onto_name\" \\\n> -\t\tgit checkout -q \"$onto^0\" || die \"could not detach HEAD\"\n> -\t# If the $onto is a proper descendant of the tip of the branch, then\n> -\t# we just fast-forwarded.\n> -\tgit update-ref ORIG_HEAD $orig_head\n> -\tmove_to_original_branch\n> -\tfinish_rebase\n> -\texit 0\n> -fi\n> -\n> -test -n \"$interactive_rebase\" && run_specific_rebase\n> -\n> -# Detach HEAD and reset the tree\n> -say \"$(gettext \"First, rewinding head to replay your work on top of it...\")\"\n> -\n> -GIT_REFLOG_ACTION=\"$GIT_REFLOG_ACTION: checkout $onto_name\" \\\n> -\tgit checkout -q \"$onto^0\" || die \"could not detach HEAD\"\n> -git update-ref ORIG_HEAD $orig_head\n> -\n> -if test -n \"$rebase_root\"\n> -then\n> -\trevisions=\"$onto..$orig_head\"\n> -else\n> -\trevisions=\"${restrict_revision-$upstream}..$orig_head\"\n> -fi\n> -\n> -run_specific_rebase\n> diff --git a/t/README b/t/README\n> index 1326fd7505..decceb8576 100644\n> --- a/t/README\n> +++ b/t/README\n> @@ -374,10 +374,6 @@ the --no-sparse command-line argument.\n>  GIT_TEST_PRELOAD_INDEX=<boolean> exercises the preload-index code path\n>  by overriding the minimum number of cache entries required per thread.\n>  \n> -GIT_TEST_REBASE_USE_BUILTIN=<boolean>, when false, disables the\n> -builtin version of git-rebase. See 'rebase.useBuiltin' in\n> -git-config(1).\n> -\n>  GIT_TEST_INDEX_THREADS=<n> enables exercising the multi-threaded loading\n>  of the index for the whole test suite by bypassing the default number of\n>  cache entries and thread minimums. Setting this to 1 will make the\n> diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh\n> index 3e73f7584c..0a88eed1db 100755\n> --- a/t/t3400-rebase.sh\n> +++ b/t/t3400-rebase.sh\n> @@ -311,4 +311,10 @@ test_expect_success 'rebase--merge.sh and --show-current-patch' '\n>  \t)\n>  '\n>  \n> +test_expect_success 'rebase -c rebase.useBuiltin=false warning' '\n> +\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN= \\\n> +\t\tgit -c rebase.useBuiltin=false rebase 2>err &&\n> +\ttest_i18ngrep \"rebase.useBuiltin support has been removed\" err\n> +'\n> +\n>  test_done\n> -- \n> 2.20.1.611.gfbb209baf1\n> \n> "},{"id":"369251","messageId":"xmqqva1nbeno.fsf@gitster-ct.c.googlers.com","threadId":"50341","inReplyTo":"20190213142209.8226-1-avarab@gmail.com","subject":"Re: [PATCH] rebase: remove the rebase.useBuiltin setting","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-02-13T20:46:03Z","receivedAt":"2019-02-13T20:46:08Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:\n\n> Remove the rebase.useBuiltin setting, which was added as an escape\n> hatch to disable the builtin version of rebase first released with Git\n> 2.20.\n> ...\n>> This patch breaks the test suite (with these two new tests) under\n>> GIT_TEST_REBASE_USE_BUILTIN=false. So a 2.21.0-rc0 regression.\n>>\n>> It would have been better to raise this before the rc period, but I just\n>> noticed this now, but we can now:\n>>\n>>  1. Skip the test under that mode\n>>  2. Fix the shell code to do the same thing\n>>  3. Just remove the shell code & GIT_TEST_REBASE_USE_BUILTIN=false mode\n>>\n>> Maybe we should just do #3. The reason for the escape hatch was in case\n>> we had bugs, and now we've had a full release cycle, but maybe that's\n>> too early...\n\nIf a new feature is added to the built-in version, I do not think it\nis a good use of our time to backport it to the scripted version, if\nonly to make the USE_BUILTIN=false test pass, especially when the\nproblematic thing is a fringe feature, lack of which would not\naffect the real users too much.\n\nSo I do agree that #2 is a bad choice.\n\nHowever, it is way too late in the cycle to say that we will ship\nwithout the escape hatch for the upcoming release, so #3 is a non\nstarter.  And you are reading too much into a full release cycle,\nwhich is merely less than 1k commits and a bit short of 3 months.\n\nIt would however be long enough to declare victory _immediately\nafter_ the upcoming release and start the next cycle without the\nescape hatch.  At that point we'd be committed to maintain only the\nbuilt-in version.\n\nThe more important every-day features should still be covered by\ntests, if the scripted ones are to be kept as escape hatch.  So to\nme #1 looks like the only sensible choice at this point, if you want\nto see a test cycle with USE_BUILTIN=false to fully pass (i.e. by\nskipping the ones that are known not to pass).\n\n"},{"id":"369261","messageId":"20190213214908.9459-1-avarab@gmail.com","threadId":"50341","inReplyTo":"xmqqva1nbeno.fsf@gitster-ct.c.googlers.com","subject":"[PATCH] rebase: fix regression in rebase.useBuiltin=false test mode","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2019-02-13T21:49:08Z","receivedAt":"2019-02-13T21:49:22Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Fix a recently introduced regression in c762aada1a (\"rebase -x: sanity\ncheck command\", 2019-01-29) triggered when running the tests with\nGIT_TEST_REBASE_USE_BUILTIN=false. See 62c23938fa (\"tests: add a\nspecial setup where rebase.useBuiltin is off\", 2018-11-14) for how\nthat test mode works.\n\nAs discussed on-list[1] it's not worth it to implement the sanity\ncheck in the legacy rebase code, we plan to remove it after the 2.21\nrelease. So let's do the bare minimum to make the tests pass under the\nGIT_TEST_REBASE_USE_BUILTIN=false special setup.\n\n1. https://public-inbox.org/git/xmqqva1nbeno.fsf@gitster-ct.c.googlers.com/\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n\nOn Wed, Feb 13 2019, Junio C Hamano wrote:\n  \n> [...]\n> It would however be long enough to declare victory _immediately\n> after_ the upcoming release and start the next cycle without the\n> escape hatch.  At that point we'd be committed to maintain only the\n> built-in version.\n>\n> The more important every-day features should still be covered by\n> tests, if the scripted ones are to be kept as escape hatch.  So to\n> me #1 looks like the only sensible choice at this point, if you want\n> to see a test cycle with USE_BUILTIN=false to fully pass (i.e. by\n> skipping the ones that are known not to pass).\n\nLet's do this for 2.21 then and I'll re-submit the legacy removal\npatch after we start 2.22.\n\n t/t3404-rebase-interactive.sh | 9 ++++++---\n 1 file changed, 6 insertions(+), 3 deletions(-)\n\ndiff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\nindex 52fa41c707..b60b11f9f2 100755\n--- a/t/t3404-rebase-interactive.sh\n+++ b/t/t3404-rebase-interactive.sh\n@@ -149,10 +149,12 @@ test_expect_success 'rebase -i with the exec command checks tree cleanness' '\n \n test_expect_success 'rebase -x with empty command fails' '\n \ttest_when_finished \"git rebase --abort ||:\" &&\n-\ttest_must_fail git rebase -x \"\" @ 2>actual &&\n+\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=true \\\n+\t\tgit rebase -x \"\" @ 2>actual &&\n \ttest_write_lines \"error: empty exec command\" >expected &&\n \ttest_i18ncmp expected actual &&\n-\ttest_must_fail git rebase -x \" \" @ 2>actual &&\n+\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=true \\\n+\t\tgit rebase -x \" \" @ 2>actual &&\n \ttest_i18ncmp expected actual\n '\n \n@@ -160,7 +162,8 @@ LF='\n '\n test_expect_success 'rebase -x with newline in command fails' '\n \ttest_when_finished \"git rebase --abort ||:\" &&\n-\ttest_must_fail git rebase -x \"a${LF}b\" @ 2>actual &&\n+\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=true \\\n+\t\tgit rebase -x \"a${LF}b\" @ 2>actual &&\n \ttest_write_lines \"error: exec commands cannot contain newlines\" \\\n \t\t\t >expected &&\n \ttest_i18ncmp expected actual\n-- \n2.20.1.611.gfbb209baf1\n\n"},{"id":"369266","messageId":"xmqqlg2j9sw5.fsf@gitster-ct.c.googlers.com","threadId":"50341","inReplyTo":"20190213214908.9459-1-avarab@gmail.com","subject":"Re: [PATCH] rebase: fix regression in rebase.useBuiltin=false test mode","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-02-13T23:21:30Z","receivedAt":"2019-02-13T23:21:36Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:\n\n> Let's do this for 2.21 then and I'll re-submit the legacy removal\n> patch after we start 2.22.\n\nOK, I would have thought that a prereq to check if the environment\nis set and skip these problematic tests would be a lot cleaner\n(primarily because the \"legacy removal\" patch will not touch the\nbody of the tests at all), but for just the coming few weeks, this\nwould suffice.\n\nThanks.\n\n>\n>  t/t3404-rebase-interactive.sh | 9 ++++++---\n>  1 file changed, 6 insertions(+), 3 deletions(-)\n>\n> diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\n> index 52fa41c707..b60b11f9f2 100755\n> --- a/t/t3404-rebase-interactive.sh\n> +++ b/t/t3404-rebase-interactive.sh\n> @@ -149,10 +149,12 @@ test_expect_success 'rebase -i with the exec command checks tree cleanness' '\n>  \n>  test_expect_success 'rebase -x with empty command fails' '\n>  \ttest_when_finished \"git rebase --abort ||:\" &&\n> -\ttest_must_fail git rebase -x \"\" @ 2>actual &&\n> +\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=true \\\n> +\t\tgit rebase -x \"\" @ 2>actual &&\n>  \ttest_write_lines \"error: empty exec command\" >expected &&\n>  \ttest_i18ncmp expected actual &&\n> -\ttest_must_fail git rebase -x \" \" @ 2>actual &&\n> +\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=true \\\n> +\t\tgit rebase -x \" \" @ 2>actual &&\n>  \ttest_i18ncmp expected actual\n>  '\n>  \n> @@ -160,7 +162,8 @@ LF='\n>  '\n>  test_expect_success 'rebase -x with newline in command fails' '\n>  \ttest_when_finished \"git rebase --abort ||:\" &&\n> -\ttest_must_fail git rebase -x \"a${LF}b\" @ 2>actual &&\n> +\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=true \\\n> +\t\tgit rebase -x \"a${LF}b\" @ 2>actual &&\n>  \ttest_write_lines \"error: exec commands cannot contain newlines\" \\\n>  \t\t\t >expected &&\n>  \ttest_i18ncmp expected actual\n"},{"id":"369314","messageId":"af4ce5d4-a788-25a6-0372-13206b161101@talktalk.net","threadId":"50341","inReplyTo":"20190213214908.9459-1-avarab@gmail.com","subject":"Re: [PATCH] rebase: fix regression in rebase.useBuiltin=false test mode","fromName":"Phillip Wood","fromEmail":"phillip.wood@talktalk.net","sentAt":"2019-02-14T16:12:17Z","receivedAt":"2019-02-14T16:12:23Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Ævar\n\nOn 13/02/2019 21:49, Ævar Arnfjörð Bjarmason wrote:\n> Fix a recently introduced regression in c762aada1a (\"rebase -x: sanity\n> check command\", 2019-01-29) triggered when running the tests with\n> GIT_TEST_REBASE_USE_BUILTIN=false. See 62c23938fa (\"tests: add a\n> special setup where rebase.useBuiltin is off\", 2018-11-14) for how\n> that test mode works.\n> \n> As discussed on-list[1] it's not worth it to implement the sanity\n> check in the legacy rebase code, we plan to remove it after the 2.21\n> release. So let's do the bare minimum to make the tests pass under the\n> GIT_TEST_REBASE_USE_BUILTIN=false special setup.\n> \n> 1. https://public-inbox.org/git/xmqqva1nbeno.fsf@gitster-ct.c.googlers.com/\n> \n\nThanks for doing this, when I wrote the original patch I decided it wasn't\nworth updating the legacy rebase but forgot about running the tests with\nrebase.useBuiltin off.\n\nBest Wishes\n\nPhillip\n\n\n> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n> ---\n> \n> On Wed, Feb 13 2019, Junio C Hamano wrote:\n>    \n>> [...]\n>> It would however be long enough to declare victory _immediately\n>> after_ the upcoming release and start the next cycle without the\n>> escape hatch.  At that point we'd be committed to maintain only the\n>> built-in version.\n>>\n>> The more important every-day features should still be covered by\n>> tests, if the scripted ones are to be kept as escape hatch.  So to\n>> me #1 looks like the only sensible choice at this point, if you want\n>> to see a test cycle with USE_BUILTIN=false to fully pass (i.e. by\n>> skipping the ones that are known not to pass).\n> \n> Let's do this for 2.21 then and I'll re-submit the legacy removal\n> patch after we start 2.22.\n> \n>   t/t3404-rebase-interactive.sh | 9 ++++++---\n>   1 file changed, 6 insertions(+), 3 deletions(-)\n> \n> diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\n> index 52fa41c707..b60b11f9f2 100755\n> --- a/t/t3404-rebase-interactive.sh\n> +++ b/t/t3404-rebase-interactive.sh\n> @@ -149,10 +149,12 @@ test_expect_success 'rebase -i with the exec command checks tree cleanness' '\n>   \n>   test_expect_success 'rebase -x with empty command fails' '\n>   \ttest_when_finished \"git rebase --abort ||:\" &&\n> -\ttest_must_fail git rebase -x \"\" @ 2>actual &&\n> +\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=true \\\n> +\t\tgit rebase -x \"\" @ 2>actual &&\n>   \ttest_write_lines \"error: empty exec command\" >expected &&\n>   \ttest_i18ncmp expected actual &&\n> -\ttest_must_fail git rebase -x \" \" @ 2>actual &&\n> +\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=true \\\n> +\t\tgit rebase -x \" \" @ 2>actual &&\n>   \ttest_i18ncmp expected actual\n>   '\n>   \n> @@ -160,7 +162,8 @@ LF='\n>   '\n>   test_expect_success 'rebase -x with newline in command fails' '\n>   \ttest_when_finished \"git rebase --abort ||:\" &&\n> -\ttest_must_fail git rebase -x \"a${LF}b\" @ 2>actual &&\n> +\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=true \\\n> +\t\tgit rebase -x \"a${LF}b\" @ 2>actual &&\n>   \ttest_write_lines \"error: exec commands cannot contain newlines\" \\\n>   \t\t\t >expected &&\n>   \ttest_i18ncmp expected actual\n> \n\n"},{"id":"371497","messageId":"20190314132444.25881-1-avarab@gmail.com","threadId":"50341","inReplyTo":"20190213142209.8226-1-avarab@gmail.com","subject":"[PATCH v2] rebase: remove the rebase.useBuiltin setting","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2019-03-14T13:24:44Z","receivedAt":"2019-03-14T13:24:59Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Remove the rebase.useBuiltin setting, which was added as an escape\nhatch to disable the builtin version of rebase first released with Git\n2.20.\n\nSee [1] for the initial implementation of rebase.useBuiltin, and [2]\nand [3] for the documentation and corresponding\nGIT_TEST_REBASE_USE_BUILTIN option.\n\nCarrying the legacy version is a maintenance burden as seen in\n7e097e27d3 (\"legacy-rebase: backport -C<n> and --whitespace=<option>\nchecks\", 2018-11-20) and 9aea5e9286 (\"rebase: fix regression in\nrebase.useBuiltin=false test mode\", 2019-02-13). Since the built-in\nversion has been shown to be stable enough let's remove the legacy\nversion.\n\nThere's still a bunch of references to git-legacy-rebase in po/*.po,\nbut those will be dealt with in time by the i18n effort.\n\n1. 55071ea248 (\"rebase: start implementing it as a builtin\",\n   2018-08-07)\n2. d8d0a546f0 (\"rebase doc: document rebase.useBuiltin\", 2018-11-14)\n3. 62c23938fa (\"tests: add a special setup where rebase.useBuiltin is\n   off\", 2018-11-14)\n---\n\nI submitted this shortly before v2.21.0 where Junio noted that he'd\nrather take the smaller 9aea5e9286 fix for that release.\n\nSo here this is again now that we've started on v2.22.0. Only trivial\nchanges:\n\n - updated commit message\n - removed legacy script from .gitignore\n - adjusted more test code for a test added in 9aea5e9286\n\n .gitignore                      |   1 -\n Documentation/config/rebase.txt |  17 +-\n Makefile                        |   1 -\n builtin/rebase.c                |  17 +-\n git-legacy-rebase.sh            | 770 --------------------------------\n t/README                        |   4 -\n t/t3400-rebase.sh               |   6 +\n t/t3404-rebase-interactive.sh   |   9 +-\n 8 files changed, 16 insertions(+), 809 deletions(-)\n delete mode 100755 git-legacy-rebase.sh\n\ndiff --git a/.gitignore b/.gitignore\nindex 7374587f9d..5cb84f1d1a 100644\n--- a/.gitignore\n+++ b/.gitignore\n@@ -82,7 +82,6 @@\n /git-init-db\n /git-interpret-trailers\n /git-instaweb\n-/git-legacy-rebase\n /git-log\n /git-ls-files\n /git-ls-remote\ndiff --git a/Documentation/config/rebase.txt b/Documentation/config/rebase.txt\nindex 331d250e04..c747452983 100644\n--- a/Documentation/config/rebase.txt\n+++ b/Documentation/config/rebase.txt\n@@ -1,16 +1,9 @@\n rebase.useBuiltin::\n-\tSet to `false` to use the legacy shellscript implementation of\n-\tlinkgit:git-rebase[1]. Is `true` by default, which means use\n-\tthe built-in rewrite of it in C.\n-+\n-The C rewrite is first included with Git version 2.20. This option\n-serves an an escape hatch to re-enable the legacy version in case any\n-bugs are found in the rewrite. This option and the shellscript version\n-of linkgit:git-rebase[1] will be removed in some future release.\n-+\n-If you find some reason to set this option to `false` other than\n-one-off testing you should report the behavior difference as a bug in\n-git.\n+\tUnused configuration variable. Used between Git version 2.20\n+\tand 2.21 as an escape hatch to enable the legacy shellscript\n+\timplementation of rebase. Now the built-in rewrite of it in C\n+\tis always used. Setting this will emit a warning, to alert any\n+\tremaining users that setting this now does nothing.\n \n rebase.stat::\n \tWhether to show a diffstat of what changed upstream since the last\ndiff --git a/Makefile b/Makefile\nindex 537493822b..9f1159cffc 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -632,7 +632,6 @@ SCRIPT_SH += git-merge-one-file.sh\n SCRIPT_SH += git-merge-resolve.sh\n SCRIPT_SH += git-mergetool.sh\n SCRIPT_SH += git-quiltimport.sh\n-SCRIPT_SH += git-legacy-rebase.sh\n SCRIPT_SH += git-remote-testgit.sh\n SCRIPT_SH += git-request-pull.sh\n SCRIPT_SH += git-stash.sh\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 52114cbf0d..829897a8fe 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -1143,21 +1143,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t};\n \tint i;\n \n-\t/*\n-\t * NEEDSWORK: Once the builtin rebase has been tested enough\n-\t * and git-legacy-rebase.sh is retired to contrib/, this preamble\n-\t * can be removed.\n-\t */\n-\n-\tif (!use_builtin_rebase()) {\n-\t\tconst char *path = mkpath(\"%s/git-legacy-rebase\",\n-\t\t\t\t\t  git_exec_path());\n-\n-\t\tif (sane_execvp(path, (char **)argv) < 0)\n-\t\t\tdie_errno(_(\"could not exec %s\"), path);\n-\t\telse\n-\t\t\tBUG(\"sane_execvp() returned???\");\n-\t}\n+\tif (!use_builtin_rebase())\n+\t\twarning(_(\"The rebase.useBuiltin support has been removed!\"));\n \n \tif (argc == 2 && !strcmp(argv[1], \"-h\"))\n \t\tusage_with_options(builtin_rebase_usage,\ndiff --git a/git-legacy-rebase.sh b/git-legacy-rebase.sh\ndeleted file mode 100755\nindex 5c2c4e5276..0000000000\n--- a/git-legacy-rebase.sh\n+++ /dev/null\n@@ -1,770 +0,0 @@\n-#!/bin/sh\n-#\n-# Copyright (c) 2005 Junio C Hamano.\n-#\n-\n-SUBDIRECTORY_OK=Yes\n-OPTIONS_KEEPDASHDASH=\n-OPTIONS_STUCKLONG=t\n-OPTIONS_SPEC=\"\\\n-git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] [<upstream>] [<branch>]\n-git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] --root [<branch>]\n-git rebase --continue | --abort | --skip | --edit-todo\n---\n- Available options are\n-v,verbose!         display a diffstat of what changed upstream\n-q,quiet!           be quiet. implies --no-stat\n-autostash          automatically stash/stash pop before and after\n-fork-point         use 'merge-base --fork-point' to refine upstream\n-onto=!             rebase onto given branch instead of upstream\n-r,rebase-merges?   try to rebase merges instead of skipping them\n-p,preserve-merges! try to recreate merges instead of ignoring them\n-s,strategy=!       use the given merge strategy\n-X,strategy-option=! pass the argument through to the merge strategy\n-no-ff!             cherry-pick all commits, even if unchanged\n-f,force-rebase!    cherry-pick all commits, even if unchanged\n-m,merge!           use merging strategies to rebase\n-i,interactive!     let the user edit the list of commits to rebase\n-x,exec=!           add exec lines after each commit of the editable list\n-k,keep-empty\t   preserve empty commits during rebase\n-allow-empty-message allow rebasing commits with empty messages\n-stat!              display a diffstat of what changed upstream\n-n,no-stat!         do not show diffstat of what changed upstream\n-verify             allow pre-rebase hook to run\n-rerere-autoupdate  allow rerere to update index with resolved conflicts\n-root!              rebase all reachable commits up to the root(s)\n-autosquash         move commits that begin with squash!/fixup! under -i\n-signoff            add a Signed-off-by: line to each commit\n-committer-date-is-author-date! passed to 'git am'\n-ignore-date!       passed to 'git am'\n-whitespace=!       passed to 'git apply'\n-ignore-whitespace! passed to 'git apply'\n-C=!                passed to 'git apply'\n-S,gpg-sign?        GPG-sign commits\n- Actions:\n-continue!          continue\n-abort!             abort and check out the original branch\n-skip!              skip current patch and continue\n-edit-todo!         edit the todo list during an interactive rebase\n-quit!              abort but keep HEAD where it is\n-show-current-patch! show the patch file being applied or merged\n-reschedule-failed-exec automatically reschedule failed exec commands\n-\"\n-. git-sh-setup\n-set_reflog_action rebase\n-require_work_tree_exists\n-cd_to_toplevel\n-\n-LF='\n-'\n-ok_to_skip_pre_rebase=\n-\n-squash_onto=\n-unset onto\n-unset restrict_revision\n-cmd=\n-strategy=\n-strategy_opts=\n-do_merge=\n-merge_dir=\"$GIT_DIR\"/rebase-merge\n-apply_dir=\"$GIT_DIR\"/rebase-apply\n-verbose=\n-diffstat=\n-test \"$(git config --bool rebase.stat)\" = true && diffstat=t\n-autostash=\"$(git config --bool rebase.autostash || echo false)\"\n-fork_point=auto\n-git_am_opt=\n-git_format_patch_opt=\n-rebase_root=\n-force_rebase=\n-allow_rerere_autoupdate=\n-# Non-empty if a rebase was in progress when 'git rebase' was invoked\n-in_progress=\n-# One of {am, merge, interactive}\n-type=\n-# One of {\"$GIT_DIR\"/rebase-apply, \"$GIT_DIR\"/rebase-merge}\n-state_dir=\n-# One of {'', continue, skip, abort}, as parsed from command line\n-action=\n-rebase_merges=\n-rebase_cousins=\n-preserve_merges=\n-autosquash=\n-keep_empty=\n-allow_empty_message=--allow-empty-message\n-signoff=\n-reschedule_failed_exec=\n-test \"$(git config --bool rebase.autosquash)\" = \"true\" && autosquash=t\n-case \"$(git config --bool commit.gpgsign)\" in\n-true)\tgpg_sign_opt=-S ;;\n-*)\tgpg_sign_opt= ;;\n-esac\n-test \"$(git config --bool rebase.reschedulefailedexec)\" = \"true\" &&\n-reschedule_failed_exec=--reschedule-failed-exec\n-. git-rebase--common\n-\n-read_basic_state () {\n-\ttest -f \"$state_dir/head-name\" &&\n-\ttest -f \"$state_dir/onto\" &&\n-\thead_name=$(cat \"$state_dir\"/head-name) &&\n-\tonto=$(cat \"$state_dir\"/onto) &&\n-\t# We always write to orig-head, but interactive rebase used to write to\n-\t# head. Fall back to reading from head to cover for the case that the\n-\t# user upgraded git with an ongoing interactive rebase.\n-\tif test -f \"$state_dir\"/orig-head\n-\tthen\n-\t\torig_head=$(cat \"$state_dir\"/orig-head)\n-\telse\n-\t\torig_head=$(cat \"$state_dir\"/head)\n-\tfi &&\n-\ttest -f \"$state_dir\"/quiet && GIT_QUIET=t\n-\ttest -f \"$state_dir\"/verbose && verbose=t\n-\ttest -f \"$state_dir\"/strategy && strategy=\"$(cat \"$state_dir\"/strategy)\"\n-\ttest -f \"$state_dir\"/strategy_opts &&\n-\t\tstrategy_opts=\"$(cat \"$state_dir\"/strategy_opts)\"\n-\ttest -f \"$state_dir\"/allow_rerere_autoupdate &&\n-\t\tallow_rerere_autoupdate=\"$(cat \"$state_dir\"/allow_rerere_autoupdate)\"\n-\ttest -f \"$state_dir\"/gpg_sign_opt &&\n-\t\tgpg_sign_opt=\"$(cat \"$state_dir\"/gpg_sign_opt)\"\n-\ttest -f \"$state_dir\"/signoff && {\n-\t\tsignoff=\"$(cat \"$state_dir\"/signoff)\"\n-\t\tforce_rebase=t\n-\t}\n-\ttest -f \"$state_dir\"/reschedule-failed-exec &&\n-\t\treschedule_failed_exec=t\n-}\n-\n-finish_rebase () {\n-\trm -f \"$(git rev-parse --git-path REBASE_HEAD)\"\n-\tapply_autostash &&\n-\t{ git gc --auto || true; } &&\n-\trm -rf \"$state_dir\"\n-}\n-\n-run_interactive () {\n-\tGIT_CHERRY_PICK_HELP=\"$resolvemsg\"\n-\texport GIT_CHERRY_PICK_HELP\n-\n-\ttest -n \"$keep_empty\" && keep_empty=\"--keep-empty\"\n-\ttest -n \"$rebase_merges\" && rebase_merges=\"--rebase-merges\"\n-\ttest -n \"$rebase_cousins\" && rebase_cousins=\"--rebase-cousins\"\n-\ttest -n \"$autosquash\" && autosquash=\"--autosquash\"\n-\ttest -n \"$verbose\" && verbose=\"--verbose\"\n-\ttest -n \"$force_rebase\" && force_rebase=\"--no-ff\"\n-\ttest -n \"$restrict_revision\" && \\\n-\t\trestrict_revision=\"--restrict-revision=^$restrict_revision\"\n-\ttest -n \"$upstream\" && upstream=\"--upstream=$upstream\"\n-\ttest -n \"$onto\" && onto=\"--onto=$onto\"\n-\ttest -n \"$squash_onto\" && squash_onto=\"--squash-onto=$squash_onto\"\n-\ttest -n \"$onto_name\" && onto_name=\"--onto-name=$onto_name\"\n-\ttest -n \"$head_name\" && head_name=\"--head-name=$head_name\"\n-\ttest -n \"$strategy\" && strategy=\"--strategy=$strategy\"\n-\ttest -n \"$strategy_opts\" && strategy_opts=\"--strategy-opts=$strategy_opts\"\n-\ttest -n \"$switch_to\" && switch_to=\"--switch-to=$switch_to\"\n-\ttest -n \"$cmd\" && cmd=\"--cmd=$cmd\"\n-\ttest -n \"$action\" && action=\"--$action\"\n-\n-\texec git rebase--interactive \"$action\" \"$keep_empty\" \"$rebase_merges\" \"$rebase_cousins\" \\\n-\t\t\"$upstream\" \"$onto\" \"$squash_onto\" \"$restrict_revision\" \\\n-\t\t\"$allow_empty_message\" \"$autosquash\" \"$verbose\" \\\n-\t\t\"$force_rebase\" \"$onto_name\" \"$head_name\" \"$strategy\" \\\n-\t\t\"$strategy_opts\" \"$cmd\" \"$switch_to\" \\\n-\t\t\"$allow_rerere_autoupdate\" \"$gpg_sign_opt\" \"$signoff\" \\\n-\t\t\"$reschedule_failed_exec\"\n-}\n-\n-run_specific_rebase () {\n-\tif [ \"$interactive_rebase\" = implied ]; then\n-\t\tGIT_SEQUENCE_EDITOR=:\n-\t\texport GIT_SEQUENCE_EDITOR\n-\t\tautosquash=\n-\tfi\n-\n-\tif test -n \"$interactive_rebase\" -a -z \"$preserve_merges\"\n-\tthen\n-\t\trun_interactive\n-\telse\n-\t\t. git-rebase--$type\n-\n-\t\tif test -z \"$preserve_merges\"\n-\t\tthen\n-\t\t\tgit_rebase__$type\n-\t\telse\n-\t\t\tgit_rebase__preserve_merges\n-\t\tfi\n-\tfi\n-\n-\tret=$?\n-\tif test $ret -eq 0\n-\tthen\n-\t\tfinish_rebase\n-\telif test $ret -eq 2 # special exit status for rebase -p\n-\tthen\n-\t\tapply_autostash &&\n-\t\trm -rf \"$state_dir\" &&\n-\t\tdie \"Nothing to do\"\n-\tfi\n-\texit $ret\n-}\n-\n-run_pre_rebase_hook () {\n-\tif test -z \"$ok_to_skip_pre_rebase\" &&\n-\t   test -x \"$(git rev-parse --git-path hooks/pre-rebase)\"\n-\tthen\n-\t\t\"$(git rev-parse --git-path hooks/pre-rebase)\" ${1+\"$@\"} ||\n-\t\tdie \"$(gettext \"The pre-rebase hook refused to rebase.\")\"\n-\tfi\n-}\n-\n-test -f \"$apply_dir\"/applying &&\n-\tdie \"$(gettext \"It looks like 'git am' is in progress. Cannot rebase.\")\"\n-\n-if test -d \"$apply_dir\"\n-then\n-\ttype=am\n-\tstate_dir=\"$apply_dir\"\n-elif test -d \"$merge_dir\"\n-then\n-\ttype=interactive\n-\tif test -d \"$merge_dir\"/rewritten\n-\tthen\n-\t\ttype=preserve-merges\n-\t\tinteractive_rebase=explicit\n-\t\tpreserve_merges=t\n-\telif test -f \"$merge_dir\"/interactive\n-\tthen\n-\t\tinteractive_rebase=explicit\n-\tfi\n-\tstate_dir=\"$merge_dir\"\n-fi\n-test -n \"$type\" && in_progress=t\n-\n-total_argc=$#\n-while test $# != 0\n-do\n-\tcase \"$1\" in\n-\t--no-verify)\n-\t\tok_to_skip_pre_rebase=yes\n-\t\t;;\n-\t--verify)\n-\t\tok_to_skip_pre_rebase=\n-\t\t;;\n-\t--continue|--skip|--abort|--quit|--edit-todo|--show-current-patch)\n-\t\ttest $total_argc -eq 2 || usage\n-\t\taction=${1##--}\n-\t\t;;\n-\t--onto=*)\n-\t\tonto=\"${1#--onto=}\"\n-\t\t;;\n-\t--exec=*)\n-\t\tcmd=\"${cmd}exec ${1#--exec=}${LF}\"\n-\t\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n-\t\t;;\n-\t--interactive)\n-\t\tinteractive_rebase=explicit\n-\t\t;;\n-\t--keep-empty)\n-\t\tkeep_empty=yes\n-\t\t;;\n-\t--allow-empty-message)\n-\t\tallow_empty_message=--allow-empty-message\n-\t\t;;\n-\t--no-keep-empty)\n-\t\tkeep_empty=\n-\t\t;;\n-\t--rebase-merges)\n-\t\trebase_merges=t\n-\t\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n-\t\t;;\n-\t--rebase-merges=*)\n-\t\trebase_merges=t\n-\t\tcase \"${1#*=}\" in\n-\t\trebase-cousins) rebase_cousins=t;;\n-\t\tno-rebase-cousins) rebase_cousins=;;\n-\t\t*) die \"Unknown mode: $1\";;\n-\t\tesac\n-\t\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n-\t\t;;\n-\t--preserve-merges)\n-\t\tpreserve_merges=t\n-\t\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n-\t\t;;\n-\t--autosquash)\n-\t\tautosquash=t\n-\t\t;;\n-\t--no-autosquash)\n-\t\tautosquash=\n-\t\t;;\n-\t--fork-point)\n-\t\tfork_point=t\n-\t\t;;\n-\t--no-fork-point)\n-\t\tfork_point=\n-\t\t;;\n-\t--merge)\n-\t\tdo_merge=t\n-\t\t;;\n-\t--strategy-option=*)\n-\t\tstrategy_opts=\"$strategy_opts $(git rev-parse --sq-quote \"--${1#--strategy-option=}\" | sed -e s/^.//)\"\n-\t\tdo_merge=t\n-\t\ttest -z \"$strategy\" && strategy=recursive\n-\t\t;;\n-\t--strategy=*)\n-\t\tstrategy=\"${1#--strategy=}\"\n-\t\tdo_merge=t\n-\t\t;;\n-\t--no-stat)\n-\t\tdiffstat=\n-\t\t;;\n-\t--stat)\n-\t\tdiffstat=t\n-\t\t;;\n-\t--autostash)\n-\t\tautostash=true\n-\t\t;;\n-\t--no-autostash)\n-\t\tautostash=false\n-\t\t;;\n-\t--verbose)\n-\t\tverbose=t\n-\t\tdiffstat=t\n-\t\tGIT_QUIET=\n-\t\t;;\n-\t--quiet)\n-\t\tGIT_QUIET=t\n-\t\tgit_am_opt=\"$git_am_opt -q\"\n-\t\tverbose=\n-\t\tdiffstat=\n-\t\t;;\n-\t--whitespace=*)\n-\t\tgit_am_opt=\"$git_am_opt --whitespace=${1#--whitespace=}\"\n-\t\tcase \"${1#--whitespace=}\" in\n-\t\tfix|strip)\n-\t\t\tforce_rebase=t\n-\t\t\t;;\n-\t\twarn|nowarn|error|error-all)\n-\t\t\t;; # okay, known whitespace option\n-\t\t*)\n-\t\t\tdie \"fatal: Invalid whitespace option: '${1#*=}'\"\n-\t\t\t;;\n-\t\tesac\n-\t\t;;\n-\t--ignore-whitespace)\n-\t\tgit_am_opt=\"$git_am_opt $1\"\n-\t\t;;\n-\t--signoff)\n-\t\tsignoff=--signoff\n-\t\t;;\n-\t--no-signoff)\n-\t\tsignoff=\n-\t\t;;\n-\t--committer-date-is-author-date|--ignore-date)\n-\t\tgit_am_opt=\"$git_am_opt $1\"\n-\t\tforce_rebase=t\n-\t\t;;\n-\t-C*[!0-9]*)\n-\t\tdie \"fatal: switch \\`C' expects a numerical value\"\n-\t\t;;\n-\t-C*)\n-\t\tgit_am_opt=\"$git_am_opt $1\"\n-\t\t;;\n-\t--root)\n-\t\trebase_root=t\n-\t\t;;\n-\t--force-rebase|--no-ff)\n-\t\tforce_rebase=t\n-\t\t;;\n-\t--rerere-autoupdate|--no-rerere-autoupdate)\n-\t\tallow_rerere_autoupdate=\"$1\"\n-\t\t;;\n-\t--gpg-sign)\n-\t\tgpg_sign_opt=-S\n-\t\t;;\n-\t--gpg-sign=*)\n-\t\tgpg_sign_opt=\"-S${1#--gpg-sign=}\"\n-\t\t;;\n-\t--reschedule-failed-exec)\n-\t\treschedule_failed_exec=--reschedule-failed-exec\n-\t\t;;\n-\t--no-reschedule-failed-exec)\n-\t\treschedule_failed_exec=\n-\t\t;;\n-\t--)\n-\t\tshift\n-\t\tbreak\n-\t\t;;\n-\t*)\n-\t\tusage\n-\t\t;;\n-\tesac\n-\tshift\n-done\n-test $# -gt 2 && usage\n-\n-if test -n \"$action\"\n-then\n-\ttest -z \"$in_progress\" && die \"$(gettext \"No rebase in progress?\")\"\n-\t# Only interactive rebase uses detailed reflog messages\n-\tif test -n \"$interactive_rebase\" && test \"$GIT_REFLOG_ACTION\" = rebase\n-\tthen\n-\t\tGIT_REFLOG_ACTION=\"rebase -i ($action)\"\n-\t\texport GIT_REFLOG_ACTION\n-\tfi\n-fi\n-\n-if test \"$action\" = \"edit-todo\" && test -z \"$interactive_rebase\"\n-then\n-\tdie \"$(gettext \"The --edit-todo action can only be used during interactive rebase.\")\"\n-fi\n-\n-case \"$action\" in\n-continue)\n-\t# Sanity check\n-\tgit rev-parse --verify HEAD >/dev/null ||\n-\t\tdie \"$(gettext \"Cannot read HEAD\")\"\n-\tgit update-index --ignore-submodules --refresh &&\n-\tgit diff-files --quiet --ignore-submodules || {\n-\t\techo \"$(gettext \"You must edit all merge conflicts and then\n-mark them as resolved using git add\")\"\n-\t\texit 1\n-\t}\n-\tread_basic_state\n-\trun_specific_rebase\n-\t;;\n-skip)\n-\toutput git reset --hard HEAD || exit $?\n-\tread_basic_state\n-\trun_specific_rebase\n-\t;;\n-abort)\n-\tgit rerere clear\n-\tread_basic_state\n-\tcase \"$head_name\" in\n-\trefs/*)\n-\t\tgit symbolic-ref -m \"rebase: aborting\" HEAD $head_name ||\n-\t\tdie \"$(eval_gettext \"Could not move back to \\$head_name\")\"\n-\t\t;;\n-\tesac\n-\toutput git reset --hard $orig_head\n-\tfinish_rebase\n-\texit\n-\t;;\n-quit)\n-\texec rm -rf \"$state_dir\"\n-\t;;\n-edit-todo)\n-\trun_specific_rebase\n-\t;;\n-show-current-patch)\n-\trun_specific_rebase\n-\tdie \"BUG: run_specific_rebase is not supposed to return here\"\n-\t;;\n-esac\n-\n-# Make sure no rebase is in progress\n-if test -n \"$in_progress\"\n-then\n-\tstate_dir_base=${state_dir##*/}\n-\tcmd_live_rebase=\"git rebase (--continue | --abort | --skip)\"\n-\tcmd_clear_stale_rebase=\"rm -fr \\\"$state_dir\\\"\"\n-\tdie \"\n-$(eval_gettext 'It seems that there is already a $state_dir_base directory, and\n-I wonder if you are in the middle of another rebase.  If that is the\n-case, please try\n-\t$cmd_live_rebase\n-If that is not the case, please\n-\t$cmd_clear_stale_rebase\n-and run me again.  I am stopping in case you still have something\n-valuable there.')\"\n-fi\n-\n-if test -n \"$rebase_root\" && test -z \"$onto\"\n-then\n-\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n-fi\n-\n-if test -n \"$keep_empty\"\n-then\n-\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n-fi\n-\n-actually_interactive=\n-if test -n \"$interactive_rebase\"\n-then\n-\tif test -z \"$preserve_merges\"\n-\tthen\n-\t\ttype=interactive\n-\telse\n-\t\ttype=preserve-merges\n-\tfi\n-\tactually_interactive=t\n-\tstate_dir=\"$merge_dir\"\n-elif test -n \"$do_merge\"\n-then\n-\tinteractive_rebase=implied\n-\ttype=interactive\n-\tstate_dir=\"$merge_dir\"\n-else\n-\ttype=am\n-\tstate_dir=\"$apply_dir\"\n-fi\n-\n-if test -t 2 && test -z \"$GIT_QUIET\"\n-then\n-\tgit_format_patch_opt=\"$git_format_patch_opt --progress\"\n-fi\n-\n-incompatible_opts=$(echo \" $git_am_opt \" | \\\n-\t\t    sed -e 's/ -q / /g' -e 's/^ \\(.*\\) $/\\1/')\n-if test -n \"$incompatible_opts\"\n-then\n-\tif test -n \"$actually_interactive\" || test \"$do_merge\"\n-\tthen\n-\t\tdie \"$(gettext \"fatal: cannot combine am options with either interactive or merge options\")\"\n-\tfi\n-fi\n-\n-if test -n \"$signoff\"\n-then\n-\ttest -n \"$preserve_merges\" &&\n-\t\tdie \"$(gettext \"fatal: cannot combine '--signoff' with '--preserve-merges'\")\"\n-\tgit_am_opt=\"$git_am_opt $signoff\"\n-\tforce_rebase=t\n-fi\n-\n-if test -n \"$preserve_merges\"\n-then\n-\t# Note: incompatibility with --signoff handled in signoff block above\n-\t# Note: incompatibility with --interactive is just a strong warning;\n-\t#       git-rebase.txt caveats with \"unless you know what you are doing\"\n-\ttest -n \"$rebase_merges\" &&\n-\t\tdie \"$(gettext \"fatal: cannot combine '--preserve-merges' with '--rebase-merges'\")\"\n-\n-\ttest -n \"$reschedule_failed_exec\" &&\n-\t\tdie \"$(gettext \"error: cannot combine '--preserve-merges' with '--reschedule-failed-exec'\")\"\n-fi\n-\n-if test -n \"$rebase_merges\"\n-then\n-\ttest -n \"$strategy_opts\" &&\n-\t\tdie \"$(gettext \"fatal: cannot combine '--rebase-merges' with '--strategy-option'\")\"\n-\ttest -n \"$strategy\" &&\n-\t\tdie \"$(gettext \"fatal: cannot combine '--rebase-merges' with '--strategy'\")\"\n-fi\n-\n-if test -z \"$rebase_root\"\n-then\n-\tcase \"$#\" in\n-\t0)\n-\t\tif ! upstream_name=$(git rev-parse --symbolic-full-name \\\n-\t\t\t--verify -q @{upstream} 2>/dev/null)\n-\t\tthen\n-\t\t\t. git-parse-remote\n-\t\t\terror_on_missing_default_upstream \"rebase\" \"rebase\" \\\n-\t\t\t\t\"against\" \"git rebase $(gettext '<branch>')\"\n-\t\tfi\n-\n-\t\ttest \"$fork_point\" = auto && fork_point=t\n-\t\t;;\n-\t*)\tupstream_name=\"$1\"\n-\t\tif test \"$upstream_name\" = \"-\"\n-\t\tthen\n-\t\t\tupstream_name=\"@{-1}\"\n-\t\tfi\n-\t\tshift\n-\t\t;;\n-\tesac\n-\tupstream=$(peel_committish \"${upstream_name}\") ||\n-\tdie \"$(eval_gettext \"invalid upstream '\\$upstream_name'\")\"\n-\tupstream_arg=\"$upstream_name\"\n-else\n-\tif test -z \"$onto\"\n-\tthen\n-\t\tempty_tree=$(git hash-object -t tree /dev/null)\n-\t\tonto=$(git commit-tree $empty_tree </dev/null)\n-\t\tsquash_onto=\"$onto\"\n-\tfi\n-\tunset upstream_name\n-\tunset upstream\n-\ttest $# -gt 1 && usage\n-\tupstream_arg=--root\n-fi\n-\n-# Make sure the branch to rebase onto is valid.\n-onto_name=${onto-\"$upstream_name\"}\n-case \"$onto_name\" in\n-*...*)\n-\tif\tleft=${onto_name%...*} right=${onto_name#*...} &&\n-\t\tonto=$(git merge-base --all ${left:-HEAD} ${right:-HEAD})\n-\tthen\n-\t\tcase \"$onto\" in\n-\t\t?*\"$LF\"?*)\n-\t\t\tdie \"$(eval_gettext \"\\$onto_name: there are more than one merge bases\")\"\n-\t\t\t;;\n-\t\t'')\n-\t\t\tdie \"$(eval_gettext \"\\$onto_name: there is no merge base\")\"\n-\t\t\t;;\n-\t\tesac\n-\telse\n-\t\tdie \"$(eval_gettext \"\\$onto_name: there is no merge base\")\"\n-\tfi\n-\t;;\n-*)\n-\tonto=$(peel_committish \"$onto_name\") ||\n-\tdie \"$(eval_gettext \"Does not point to a valid commit: \\$onto_name\")\"\n-\t;;\n-esac\n-\n-# If the branch to rebase is given, that is the branch we will rebase\n-# $branch_name -- branch/commit being rebased, or HEAD (already detached)\n-# $orig_head -- commit object name of tip of the branch before rebasing\n-# $head_name -- refs/heads/<that-branch> or \"detached HEAD\"\n-switch_to=\n-case \"$#\" in\n-1)\n-\t# Is it \"rebase other $branchname\" or \"rebase other $commit\"?\n-\tbranch_name=\"$1\"\n-\tswitch_to=\"$1\"\n-\n-\t# Is it a local branch?\n-\tif git show-ref --verify --quiet -- \"refs/heads/$branch_name\" &&\n-\t   orig_head=$(git rev-parse -q --verify \"refs/heads/$branch_name\")\n-\tthen\n-\t\thead_name=\"refs/heads/$branch_name\"\n-\t# If not is it a valid ref (branch or commit)?\n-\telif orig_head=$(git rev-parse -q --verify \"$branch_name\")\n-\tthen\n-\t\thead_name=\"detached HEAD\"\n-\n-\telse\n-\t\tdie \"$(eval_gettext \"fatal: no such branch/commit '\\$branch_name'\")\"\n-\tfi\n-\t;;\n-0)\n-\t# Do not need to switch branches, we are already on it.\n-\tif branch_name=$(git symbolic-ref -q HEAD)\n-\tthen\n-\t\thead_name=$branch_name\n-\t\tbranch_name=$(expr \"z$branch_name\" : 'zrefs/heads/\\(.*\\)')\n-\telse\n-\t\thead_name=\"detached HEAD\"\n-\t\tbranch_name=HEAD\n-\tfi\n-\torig_head=$(git rev-parse --verify HEAD) || exit\n-\t;;\n-*)\n-\tdie \"BUG: unexpected number of arguments left to parse\"\n-\t;;\n-esac\n-\n-if test \"$fork_point\" = t\n-then\n-\tnew_upstream=$(git merge-base --fork-point \"$upstream_name\" \\\n-\t\t\t\"${switch_to:-HEAD}\")\n-\tif test -n \"$new_upstream\"\n-\tthen\n-\t\trestrict_revision=$new_upstream\n-\tfi\n-fi\n-\n-if test \"$autostash\" = true && ! (require_clean_work_tree) 2>/dev/null\n-then\n-\tstash_sha1=$(git stash create \"autostash\") ||\n-\tdie \"$(gettext 'Cannot autostash')\"\n-\n-\tmkdir -p \"$state_dir\" &&\n-\techo $stash_sha1 >\"$state_dir/autostash\" &&\n-\tstash_abbrev=$(git rev-parse --short $stash_sha1) &&\n-\techo \"$(eval_gettext 'Created autostash: $stash_abbrev')\" &&\n-\tgit reset --hard\n-fi\n-\n-require_clean_work_tree \"rebase\" \"$(gettext \"Please commit or stash them.\")\"\n-\n-# Now we are rebasing commits $upstream..$orig_head (or with --root,\n-# everything leading up to $orig_head) on top of $onto\n-\n-# Check if we are already based on $onto with linear history,\n-# but this should be done only when upstream and onto are the same\n-# and if this is not an interactive rebase.\n-mb=$(git merge-base \"$onto\" \"$orig_head\")\n-if test -z \"$actually_interactive\" && test \"$upstream\" = \"$onto\" &&\n-\ttest \"$mb\" = \"$onto\" && test -z \"$restrict_revision\" &&\n-\t# linear history?\n-\t! (git rev-list --parents \"$onto\"..\"$orig_head\" | sane_grep \" .* \") > /dev/null\n-then\n-\tif test -z \"$force_rebase\"\n-\tthen\n-\t\t# Lazily switch to the target branch if needed...\n-\t\ttest -z \"$switch_to\" ||\n-\t\tGIT_REFLOG_ACTION=\"$GIT_REFLOG_ACTION: checkout $switch_to\" \\\n-\t\t\tgit checkout -q \"$switch_to\" --\n-\t\tif test \"$branch_name\" = \"HEAD\" &&\n-\t\t\t ! git symbolic-ref -q HEAD\n-\t\tthen\n-\t\t\tsay \"$(eval_gettext \"HEAD is up to date.\")\"\n-\t\telse\n-\t\t\tsay \"$(eval_gettext \"Current branch \\$branch_name is up to date.\")\"\n-\t\tfi\n-\t\tfinish_rebase\n-\t\texit 0\n-\telse\n-\t\tif test \"$branch_name\" = \"HEAD\" &&\n-\t\t\t ! git symbolic-ref -q HEAD\n-\t\tthen\n-\t\t\tsay \"$(eval_gettext \"HEAD is up to date, rebase forced.\")\"\n-\t\telse\n-\t\t\tsay \"$(eval_gettext \"Current branch \\$branch_name is up to date, rebase forced.\")\"\n-\t\tfi\n-\tfi\n-fi\n-\n-# If a hook exists, give it a chance to interrupt\n-run_pre_rebase_hook \"$upstream_arg\" \"$@\"\n-\n-if test -n \"$diffstat\"\n-then\n-\tif test -n \"$verbose\"\n-\tthen\n-\t\tif test -z \"$mb\"\n-\t\tthen\n-\t\t\techo \"$(eval_gettext \"Changes to \\$onto:\")\"\n-\t\telse\n-\t\t\techo \"$(eval_gettext \"Changes from \\$mb to \\$onto:\")\"\n-\t\tfi\n-\tfi\n-\tmb_tree=\"${mb:-$(git hash-object -t tree /dev/null)}\"\n-\t# We want color (if set), but no pager\n-\tGIT_PAGER='' git diff --stat --summary \"$mb_tree\" \"$onto\"\n-fi\n-\n-if test -z \"$actually_interactive\" && test \"$mb\" = \"$orig_head\"\n-then\n-\tsay \"$(eval_gettext \"Fast-forwarded \\$branch_name to \\$onto_name.\")\"\n-\tGIT_REFLOG_ACTION=\"$GIT_REFLOG_ACTION: checkout $onto_name\" \\\n-\t\tgit checkout -q \"$onto^0\" || die \"could not detach HEAD\"\n-\t# If the $onto is a proper descendant of the tip of the branch, then\n-\t# we just fast-forwarded.\n-\tgit update-ref ORIG_HEAD $orig_head\n-\tmove_to_original_branch\n-\tfinish_rebase\n-\texit 0\n-fi\n-\n-test -n \"$interactive_rebase\" && run_specific_rebase\n-\n-# Detach HEAD and reset the tree\n-say \"$(gettext \"First, rewinding head to replay your work on top of it...\")\"\n-\n-GIT_REFLOG_ACTION=\"$GIT_REFLOG_ACTION: checkout $onto_name\" \\\n-\tgit checkout -q \"$onto^0\" || die \"could not detach HEAD\"\n-git update-ref ORIG_HEAD $orig_head\n-\n-if test -n \"$rebase_root\"\n-then\n-\trevisions=\"$onto..$orig_head\"\n-else\n-\trevisions=\"${restrict_revision-$upstream}..$orig_head\"\n-fi\n-\n-run_specific_rebase\ndiff --git a/t/README b/t/README\nindex 7a3d582267..385262357b 100644\n--- a/t/README\n+++ b/t/README\n@@ -379,10 +379,6 @@ the --no-sparse command-line argument.\n GIT_TEST_PRELOAD_INDEX=<boolean> exercises the preload-index code path\n by overriding the minimum number of cache entries required per thread.\n \n-GIT_TEST_REBASE_USE_BUILTIN=<boolean>, when false, disables the\n-builtin version of git-rebase. See 'rebase.useBuiltin' in\n-git-config(1).\n-\n GIT_TEST_INDEX_THREADS=<n> enables exercising the multi-threaded loading\n of the index for the whole test suite by bypassing the default number of\n cache entries and thread minimums. Setting this to 1 will make the\ndiff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh\nindex 3e73f7584c..0a88eed1db 100755\n--- a/t/t3400-rebase.sh\n+++ b/t/t3400-rebase.sh\n@@ -311,4 +311,10 @@ test_expect_success 'rebase--merge.sh and --show-current-patch' '\n \t)\n '\n \n+test_expect_success 'rebase -c rebase.useBuiltin=false warning' '\n+\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN= \\\n+\t\tgit -c rebase.useBuiltin=false rebase 2>err &&\n+\ttest_i18ngrep \"rebase.useBuiltin support has been removed\" err\n+'\n+\n test_done\ndiff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\nindex b60b11f9f2..1723e1a858 100755\n--- a/t/t3404-rebase-interactive.sh\n+++ b/t/t3404-rebase-interactive.sh\n@@ -149,12 +149,10 @@ test_expect_success 'rebase -i with the exec command checks tree cleanness' '\n \n test_expect_success 'rebase -x with empty command fails' '\n \ttest_when_finished \"git rebase --abort ||:\" &&\n-\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=true \\\n-\t\tgit rebase -x \"\" @ 2>actual &&\n+\ttest_must_fail env git rebase -x \"\" @ 2>actual &&\n \ttest_write_lines \"error: empty exec command\" >expected &&\n \ttest_i18ncmp expected actual &&\n-\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=true \\\n-\t\tgit rebase -x \" \" @ 2>actual &&\n+\ttest_must_fail env git rebase -x \" \" @ 2>actual &&\n \ttest_i18ncmp expected actual\n '\n \n@@ -162,8 +160,7 @@ LF='\n '\n test_expect_success 'rebase -x with newline in command fails' '\n \ttest_when_finished \"git rebase --abort ||:\" &&\n-\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=true \\\n-\t\tgit rebase -x \"a${LF}b\" @ 2>actual &&\n+\ttest_must_fail env git rebase -x \"a${LF}b\" @ 2>actual &&\n \ttest_write_lines \"error: exec commands cannot contain newlines\" \\\n \t\t\t >expected &&\n \ttest_i18ncmp expected actual\n-- \n2.21.0.360.g471c308f928\n\n"},{"id":"371506","messageId":"nycvar.QRO.7.76.6.1903141544110.41@tvgsbejvaqbjf.bet","threadId":"50341","inReplyTo":"20190314132444.25881-1-avarab@gmail.com","subject":"Re: [PATCH v2] rebase: remove the rebase.useBuiltin setting","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2019-03-14T14:58:43Z","receivedAt":"2019-03-14T14:59:13Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Ævar,\n\nOn Thu, 14 Mar 2019, Ævar Arnfjörð Bjarmason wrote:\n\n> Remove the rebase.useBuiltin setting, which was added as an escape\n> hatch to disable the builtin version of rebase first released with Git\n> 2.20.\n> \n> See [1] for the initial implementation of rebase.useBuiltin, and [2]\n> and [3] for the documentation and corresponding\n> GIT_TEST_REBASE_USE_BUILTIN option.\n> \n> Carrying the legacy version is a maintenance burden as seen in\n> 7e097e27d3 (\"legacy-rebase: backport -C<n> and --whitespace=<option>\n> checks\", 2018-11-20) and 9aea5e9286 (\"rebase: fix regression in\n> rebase.useBuiltin=false test mode\", 2019-02-13). Since the built-in\n> version has been shown to be stable enough let's remove the legacy\n> version.\n\nI agree with that reasoning. Elsewhere, a wish cropped up for the `git\nstash` command to optionally ignore unmatched globs, and if we go about to\nimplement this, we will have to implement it in the scripted and the\nbuilt-in version. If we can at least avoid that for the `rebase` command,\nI think it would make things a bit easier over here.\n\n> diff --git a/Documentation/config/rebase.txt b/Documentation/config/rebase.txt\n> index 331d250e04..c747452983 100644\n> --- a/Documentation/config/rebase.txt\n> +++ b/Documentation/config/rebase.txt\n> @@ -1,16 +1,9 @@\n>  rebase.useBuiltin::\n> -\tSet to `false` to use the legacy shellscript implementation of\n> -\tlinkgit:git-rebase[1]. Is `true` by default, which means use\n> -\tthe built-in rewrite of it in C.\n> -+\n> -The C rewrite is first included with Git version 2.20. This option\n> -serves an an escape hatch to re-enable the legacy version in case any\n> -bugs are found in the rewrite. This option and the shellscript version\n> -of linkgit:git-rebase[1] will be removed in some future release.\n> -+\n> -If you find some reason to set this option to `false` other than\n> -one-off testing you should report the behavior difference as a bug in\n> -git.\n> +\tUnused configuration variable. Used between Git version 2.20\n> +\tand 2.21 as an escape hatch to enable the legacy shellscript\n> +\timplementation of rebase. Now the built-in rewrite of it in C\n> +\tis always used. Setting this will emit a warning, to alert any\n> +\tremaining users that setting this now does nothing.\n\nDo we really need to document this? Why not just remove the entire entry\nwholesale; the warning if `rebase.useBuiltin=false` is set will be\ninformative enough.\n\n> diff --git a/builtin/rebase.c b/builtin/rebase.c\n> index 52114cbf0d..829897a8fe 100644\n> --- a/builtin/rebase.c\n> +++ b/builtin/rebase.c\n> @@ -1143,21 +1143,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>  \t};\n>  \tint i;\n>  \n> -\t/*\n> -\t * NEEDSWORK: Once the builtin rebase has been tested enough\n> -\t * and git-legacy-rebase.sh is retired to contrib/, this preamble\n> -\t * can be removed.\n> -\t */\n> -\n> -\tif (!use_builtin_rebase()) {\n> -\t\tconst char *path = mkpath(\"%s/git-legacy-rebase\",\n> -\t\t\t\t\t  git_exec_path());\n> -\n> -\t\tif (sane_execvp(path, (char **)argv) < 0)\n> -\t\t\tdie_errno(_(\"could not exec %s\"), path);\n> -\t\telse\n> -\t\t\tBUG(\"sane_execvp() returned???\");\n> -\t}\n> +\tif (!use_builtin_rebase())\n> +\t\twarning(_(\"The rebase.useBuiltin support has been removed!\"));\n\nA couple of thoughts about this:\n\n- `use_builtin_rebase()` spawns a `git config`. This is a pretty expensive\n  operation on Windows (even if it might not matter in the big scheme of\n  things, as the couple of milliseconds are probably a mere drop on a hot\n  stone compared to the I/O incurred by the recursive merge), and it was\n  only done in that way to allow for spawning the legacy rebase without\n  having touched any global state (such as setting `GIT_*` environment\n  variables when a Git directory was discovered).\n\n  Couldn't we rather move this warning into `rebase_config()`?\n\n- The warning should start with a lower-case letter (why don't we have any\n  automated linter for this? This is a totally automatable thing that\n  could run as part of `make` when `DEVELOPER` is set, maybe just on the\n  `git diff HEAD --` part, and maybe even generating a patch that can be\n  applied; No human should *ever* need to spend time on such issues).\n\n- That warning should probably talk more specifically about the scripted\n  version having been removed, not only the option (which was actually not\n  removed, otherwise the user would not see that warning ;-)).\n\n> diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh\n> index 3e73f7584c..0a88eed1db 100755\n> --- a/t/t3400-rebase.sh\n> +++ b/t/t3400-rebase.sh\n> @@ -311,4 +311,10 @@ test_expect_success 'rebase--merge.sh and --show-current-patch' '\n>  \t)\n>  '\n>  \n> +test_expect_success 'rebase -c rebase.useBuiltin=false warning' '\n> +\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN= \\\n\nGood attention to detail! I would have forgotten to unset that environment\nvariable.\n\n> +\t\tgit -c rebase.useBuiltin=false rebase 2>err &&\n> +\ttest_i18ngrep \"rebase.useBuiltin support has been removed\" err\n> +'\n> +\n>  test_done\n> diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\n> index b60b11f9f2..1723e1a858 100755\n> --- a/t/t3404-rebase-interactive.sh\n> +++ b/t/t3404-rebase-interactive.sh\n> @@ -149,12 +149,10 @@ test_expect_success 'rebase -i with the exec command checks tree cleanness' '\n>  \n>  test_expect_success 'rebase -x with empty command fails' '\n>  \ttest_when_finished \"git rebase --abort ||:\" &&\n> -\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=true \\\n> -\t\tgit rebase -x \"\" @ 2>actual &&\n> +\ttest_must_fail env git rebase -x \"\" @ 2>actual &&\n>  \ttest_write_lines \"error: empty exec command\" >expected &&\n>  \ttest_i18ncmp expected actual &&\n> -\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=true \\\n> -\t\tgit rebase -x \" \" @ 2>actual &&\n> +\ttest_must_fail env git rebase -x \" \" @ 2>actual &&\n>  \ttest_i18ncmp expected actual\n>  '\n>  \n> @@ -162,8 +160,7 @@ LF='\n>  '\n>  test_expect_success 'rebase -x with newline in command fails' '\n>  \ttest_when_finished \"git rebase --abort ||:\" &&\n> -\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=true \\\n> -\t\tgit rebase -x \"a${LF}b\" @ 2>actual &&\n> +\ttest_must_fail env git rebase -x \"a${LF}b\" @ 2>actual &&\n\nNot a terribly big deal, but I would have structured the patch (series) by\nleaving this change to t3404 as a 2/2, as it is not technically necessary\nto include those changes in 1/2 (if your goal is, as mine usually is, to\n\"go from working state to working state\" between commits).\n\nThank you for keeping on the track with this,\nDscho\n\n>  \ttest_write_lines \"error: exec commands cannot contain newlines\" \\\n>  \t\t\t >expected &&\n>  \ttest_i18ncmp expected actual\n> -- \n> 2.21.0.360.g471c308f928\n> \n> "},{"id":"371514","messageId":"87ef79bho5.fsf@evledraar.gmail.com","threadId":"50341","inReplyTo":"nycvar.QRO.7.76.6.1903141544110.41@tvgsbejvaqbjf.bet","subject":"Re: [PATCH v2] rebase: remove the rebase.useBuiltin setting","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2019-03-14T15:27:06Z","receivedAt":"2019-03-14T15:27:11Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Thu, Mar 14 2019, Johannes Schindelin wrote:\n\n> Hi Ævar,\n>\n> On Thu, 14 Mar 2019, Ævar Arnfjörð Bjarmason wrote:\n>\n>> Remove the rebase.useBuiltin setting, which was added as an escape\n>> hatch to disable the builtin version of rebase first released with Git\n>> 2.20.\n>>\n>> See [1] for the initial implementation of rebase.useBuiltin, and [2]\n>> and [3] for the documentation and corresponding\n>> GIT_TEST_REBASE_USE_BUILTIN option.\n>>\n>> Carrying the legacy version is a maintenance burden as seen in\n>> 7e097e27d3 (\"legacy-rebase: backport -C<n> and --whitespace=<option>\n>> checks\", 2018-11-20) and 9aea5e9286 (\"rebase: fix regression in\n>> rebase.useBuiltin=false test mode\", 2019-02-13). Since the built-in\n>> version has been shown to be stable enough let's remove the legacy\n>> version.\n>\n> I agree with that reasoning. Elsewhere, a wish cropped up for the `git\n> stash` command to optionally ignore unmatched globs, and if we go about to\n> implement this, we will have to implement it in the scripted and the\n> built-in version. If we can at least avoid that for the `rebase` command,\n> I think it would make things a bit easier over here.\n>\n>> diff --git a/Documentation/config/rebase.txt b/Documentation/config/rebase.txt\n>> index 331d250e04..c747452983 100644\n>> --- a/Documentation/config/rebase.txt\n>> +++ b/Documentation/config/rebase.txt\n>> @@ -1,16 +1,9 @@\n>>  rebase.useBuiltin::\n>> -\tSet to `false` to use the legacy shellscript implementation of\n>> -\tlinkgit:git-rebase[1]. Is `true` by default, which means use\n>> -\tthe built-in rewrite of it in C.\n>> -+\n>> -The C rewrite is first included with Git version 2.20. This option\n>> -serves an an escape hatch to re-enable the legacy version in case any\n>> -bugs are found in the rewrite. This option and the shellscript version\n>> -of linkgit:git-rebase[1] will be removed in some future release.\n>> -+\n>> -If you find some reason to set this option to `false` other than\n>> -one-off testing you should report the behavior difference as a bug in\n>> -git.\n>> +\tUnused configuration variable. Used between Git version 2.20\n>> +\tand 2.21 as an escape hatch to enable the legacy shellscript\n>> +\timplementation of rebase. Now the built-in rewrite of it in C\n>> +\tis always used. Setting this will emit a warning, to alert any\n>> +\tremaining users that setting this now does nothing.\n>\n> Do we really need to document this? Why not just remove the entire entry\n> wholesale; the warning if `rebase.useBuiltin=false` is set will be\n> informative enough.\n\nI don't have a super-strong preference in this case, but in general I\nthink it makes sense to have docs for this too.\n\nIndividual versions of git tend to be around for a while due to distro\npackaging timelines, so e.g. if we're \"lucky\" a given version like 2.21\nmight be installed on say OSX for half a decade.\n\nThat'll mean some people probably setting this in config, and then when\nthey later wonder if it's needed they can Google search the config\noption name or check it in git-config, less of a stretch than needing to\nknow to run git-rebase with the option...\n\n>> diff --git a/builtin/rebase.c b/builtin/rebase.c\n>> index 52114cbf0d..829897a8fe 100644\n>> --- a/builtin/rebase.c\n>> +++ b/builtin/rebase.c\n>> @@ -1143,21 +1143,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>>  \t};\n>>  \tint i;\n>>\n>> -\t/*\n>> -\t * NEEDSWORK: Once the builtin rebase has been tested enough\n>> -\t * and git-legacy-rebase.sh is retired to contrib/, this preamble\n>> -\t * can be removed.\n>> -\t */\n>> -\n>> -\tif (!use_builtin_rebase()) {\n>> -\t\tconst char *path = mkpath(\"%s/git-legacy-rebase\",\n>> -\t\t\t\t\t  git_exec_path());\n>> -\n>> -\t\tif (sane_execvp(path, (char **)argv) < 0)\n>> -\t\t\tdie_errno(_(\"could not exec %s\"), path);\n>> -\t\telse\n>> -\t\t\tBUG(\"sane_execvp() returned???\");\n>> -\t}\n>> +\tif (!use_builtin_rebase())\n>> +\t\twarning(_(\"The rebase.useBuiltin support has been removed!\"));\n>\n> A couple of thoughts about this:\n>\n> - `use_builtin_rebase()` spawns a `git config`. This is a pretty expensive\n>   operation on Windows (even if it might not matter in the big scheme of\n>   things, as the couple of milliseconds are probably a mere drop on a hot\n>   stone compared to the I/O incurred by the recursive merge), and it was\n>   only done in that way to allow for spawning the legacy rebase without\n>   having touched any global state (such as setting `GIT_*` environment\n>   variables when a Git directory was discovered).\n>\n>   Couldn't we rather move this warning into `rebase_config()`?\n>\n> - The warning should start with a lower-case letter (why don't we have any\n>   automated linter for this? This is a totally automatable thing that\n>   could run as part of `make` when `DEVELOPER` is set, maybe just on the\n>   `git diff HEAD --` part, and maybe even generating a patch that can be\n>   applied; No human should *ever* need to spend time on such issues).\n\nBoth of these make sense. Will have that in a v3 pending further\nfeedback. Didn't notice that strange use_builtin_rebase()\nimplementation.\n\n> - That warning should probably talk more specifically about the scripted\n>   version having been removed, not only the option (which was actually not\n>   removed, otherwise the user would not see that warning ;-)).\n\n...or just change it to briefly refer to the git-config docs where all\nof this will be explained :)\n\n>> diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh\n>> index 3e73f7584c..0a88eed1db 100755\n>> --- a/t/t3400-rebase.sh\n>> +++ b/t/t3400-rebase.sh\n>> @@ -311,4 +311,10 @@ test_expect_success 'rebase--merge.sh and --show-current-patch' '\n>>  \t)\n>>  '\n>>\n>> +test_expect_success 'rebase -c rebase.useBuiltin=false warning' '\n>> +\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN= \\\n>\n> Good attention to detail! I would have forgotten to unset that environment\n> variable.\n>\n>> +\t\tgit -c rebase.useBuiltin=false rebase 2>err &&\n>> +\ttest_i18ngrep \"rebase.useBuiltin support has been removed\" err\n>> +'\n>> +\n>>  test_done\n>> diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\n>> index b60b11f9f2..1723e1a858 100755\n>> --- a/t/t3404-rebase-interactive.sh\n>> +++ b/t/t3404-rebase-interactive.sh\n>> @@ -149,12 +149,10 @@ test_expect_success 'rebase -i with the exec command checks tree cleanness' '\n>>\n>>  test_expect_success 'rebase -x with empty command fails' '\n>>  \ttest_when_finished \"git rebase --abort ||:\" &&\n>> -\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=true \\\n>> -\t\tgit rebase -x \"\" @ 2>actual &&\n>> +\ttest_must_fail env git rebase -x \"\" @ 2>actual &&\n>>  \ttest_write_lines \"error: empty exec command\" >expected &&\n>>  \ttest_i18ncmp expected actual &&\n>> -\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=true \\\n>> -\t\tgit rebase -x \" \" @ 2>actual &&\n>> +\ttest_must_fail env git rebase -x \" \" @ 2>actual &&\n>>  \ttest_i18ncmp expected actual\n>>  '\n>>\n>> @@ -162,8 +160,7 @@ LF='\n>>  '\n>>  test_expect_success 'rebase -x with newline in command fails' '\n>>  \ttest_when_finished \"git rebase --abort ||:\" &&\n>> -\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=true \\\n>> -\t\tgit rebase -x \"a${LF}b\" @ 2>actual &&\n>> +\ttest_must_fail env git rebase -x \"a${LF}b\" @ 2>actual &&\n>\n> Not a terribly big deal, but I would have structured the patch (series) by\n> leaving this change to t3404 as a 2/2, as it is not technically necessary\n> to include those changes in 1/2 (if your goal is, as mine usually is, to\n> \"go from working state to working state\" between commits).\n\nI run the test suite on various git versions, including for bisecting\npurposes and with various GIT_TEST_* options on.\n\nI'll probably never bump into *this* particular commit for this option,\nbut in general I think it makes more sense to not break the test suite\nunder existing GIT_TEST_* flags, unless it's a breakage where e.g. we\nsay \"this isn't supported anymore\".\n\nBy splitting this up as you suggest the 1/2 of those would be a head\nscratching breakage under GIT_TEST_REBASE_USE_BUILTIN=false, and only\nunder 2/2 would we show via the warning why it was failing.\n"},{"id":"371591","messageId":"20190315134548.24479-1-avarab@gmail.com","threadId":"50341","inReplyTo":"87ef79bho5.fsf@evledraar.gmail.com","subject":"[PATCH v3] rebase: remove the rebase.useBuiltin setting","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2019-03-15T13:45:48Z","receivedAt":"2019-03-15T13:46:02Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Remove the rebase.useBuiltin setting, which was added as an escape\nhatch to disable the builtin version of rebase first released with Git\n2.20.\n\nSee [1] for the initial implementation of rebase.useBuiltin, and [2]\nand [3] for the documentation and corresponding\nGIT_TEST_REBASE_USE_BUILTIN option.\n\nCarrying the legacy version is a maintenance burden as seen in\n7e097e27d3 (\"legacy-rebase: backport -C<n> and --whitespace=<option>\nchecks\", 2018-11-20) and 9aea5e9286 (\"rebase: fix regression in\nrebase.useBuiltin=false test mode\", 2019-02-13). Since the built-in\nversion has been shown to be stable enough let's remove the legacy\nversion.\n\nAs noted in [3] having use_builtin_rebase() shell out to get its\nconfig doesn't make any sense anymore, that was done for the purposes\nof spawning the legacy rebase without having modified any global\nstate. Let's instead handle this case in rebase_config().\n\nThere's still a bunch of references to git-legacy-rebase in po/*.po,\nbut those will be dealt with in time by the i18n effort.\n\nEven though this configuration variable only existed for one release\nlet's not entirely delete the entry from the docs, but note its\nabsence. Individual versions of git tend to be around for a while due\nto distro packaging timelines, so e.g. if we're \"lucky\" a given\nversion like 2.21 might be installed on say OSX for half a decade.\n\nThat'll mean some people probably setting this in config, and then\nwhen they later wonder if it's needed they can Google search the\nconfig option name or check it in git-config. It also allows us to\nrefer to the docs from the warning for details.\n\n1. 55071ea248 (\"rebase: start implementing it as a builtin\",\n   2018-08-07)\n2. d8d0a546f0 (\"rebase doc: document rebase.useBuiltin\", 2018-11-14)\n3. 62c23938fa (\"tests: add a special setup where rebase.useBuiltin is\n   off\", 2018-11-14)\n3. https://public-inbox.org/git/nycvar.QRO.7.76.6.1903141544110.41@tvgsbejvaqbjf.bet/\n---\n\nAddresses Johannes's comments on v2, and improves the tests I'm adding\nto cover both the env var & config variable.\n\n .gitignore                      |   1 -\n Documentation/config/rebase.txt |  17 +-\n Makefile                        |   1 -\n builtin/rebase.c                |  50 +--\n git-legacy-rebase.sh            | 770 --------------------------------\n t/README                        |   4 -\n t/t3400-rebase.sh               |  16 +\n t/t3404-rebase-interactive.sh   |   9 +-\n 8 files changed, 35 insertions(+), 833 deletions(-)\n delete mode 100755 git-legacy-rebase.sh\n\ndiff --git a/.gitignore b/.gitignore\nindex 7374587f9d..5cb84f1d1a 100644\n--- a/.gitignore\n+++ b/.gitignore\n@@ -82,7 +82,6 @@\n /git-init-db\n /git-interpret-trailers\n /git-instaweb\n-/git-legacy-rebase\n /git-log\n /git-ls-files\n /git-ls-remote\ndiff --git a/Documentation/config/rebase.txt b/Documentation/config/rebase.txt\nindex 331d250e04..c747452983 100644\n--- a/Documentation/config/rebase.txt\n+++ b/Documentation/config/rebase.txt\n@@ -1,16 +1,9 @@\n rebase.useBuiltin::\n-\tSet to `false` to use the legacy shellscript implementation of\n-\tlinkgit:git-rebase[1]. Is `true` by default, which means use\n-\tthe built-in rewrite of it in C.\n-+\n-The C rewrite is first included with Git version 2.20. This option\n-serves an an escape hatch to re-enable the legacy version in case any\n-bugs are found in the rewrite. This option and the shellscript version\n-of linkgit:git-rebase[1] will be removed in some future release.\n-+\n-If you find some reason to set this option to `false` other than\n-one-off testing you should report the behavior difference as a bug in\n-git.\n+\tUnused configuration variable. Used between Git version 2.20\n+\tand 2.21 as an escape hatch to enable the legacy shellscript\n+\timplementation of rebase. Now the built-in rewrite of it in C\n+\tis always used. Setting this will emit a warning, to alert any\n+\tremaining users that setting this now does nothing.\n \n rebase.stat::\n \tWhether to show a diffstat of what changed upstream since the last\ndiff --git a/Makefile b/Makefile\nindex 537493822b..9f1159cffc 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -632,7 +632,6 @@ SCRIPT_SH += git-merge-one-file.sh\n SCRIPT_SH += git-merge-resolve.sh\n SCRIPT_SH += git-mergetool.sh\n SCRIPT_SH += git-quiltimport.sh\n-SCRIPT_SH += git-legacy-rebase.sh\n SCRIPT_SH += git-remote-testgit.sh\n SCRIPT_SH += git-request-pull.sh\n SCRIPT_SH += git-stash.sh\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 52114cbf0d..bc3dc629c1 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -46,29 +46,6 @@ enum rebase_type {\n \tREBASE_PRESERVE_MERGES\n };\n \n-static int use_builtin_rebase(void)\n-{\n-\tstruct child_process cp = CHILD_PROCESS_INIT;\n-\tstruct strbuf out = STRBUF_INIT;\n-\tint ret, env = git_env_bool(\"GIT_TEST_REBASE_USE_BUILTIN\", -1);\n-\n-\tif (env != -1)\n-\t\treturn env;\n-\n-\targv_array_pushl(&cp.args,\n-\t\t\t \"config\", \"--bool\", \"rebase.usebuiltin\", NULL);\n-\tcp.git_cmd = 1;\n-\tif (capture_command(&cp, &out, 6)) {\n-\t\tstrbuf_release(&out);\n-\t\treturn 1;\n-\t}\n-\n-\tstrbuf_trim(&out);\n-\tret = !strcmp(\"true\", out.buf);\n-\tstrbuf_release(&out);\n-\treturn ret;\n-}\n-\n struct rebase_options {\n \tenum rebase_type type;\n \tconst char *state_dir;\n@@ -106,6 +83,7 @@ struct rebase_options {\n \tchar *strategy, *strategy_opts;\n \tstruct strbuf git_format_patch_opt;\n \tint reschedule_failed_exec;\n+\tint use_legacy_rebase;\n };\n \n static int is_interactive(struct rebase_options *opts)\n@@ -869,6 +847,11 @@ static int rebase_config(const char *var, const char *value, void *data)\n \t\treturn 0;\n \t}\n \n+\tif (!strcmp(var, \"rebase.usebuiltin\")) {\n+\t\topts->use_legacy_rebase = !git_config_bool(var, value);\n+\t\treturn 0;\n+\t}\n+\n \treturn git_default_config(var, value, data);\n }\n \n@@ -1143,22 +1126,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t};\n \tint i;\n \n-\t/*\n-\t * NEEDSWORK: Once the builtin rebase has been tested enough\n-\t * and git-legacy-rebase.sh is retired to contrib/, this preamble\n-\t * can be removed.\n-\t */\n-\n-\tif (!use_builtin_rebase()) {\n-\t\tconst char *path = mkpath(\"%s/git-legacy-rebase\",\n-\t\t\t\t\t  git_exec_path());\n-\n-\t\tif (sane_execvp(path, (char **)argv) < 0)\n-\t\t\tdie_errno(_(\"could not exec %s\"), path);\n-\t\telse\n-\t\t\tBUG(\"sane_execvp() returned???\");\n-\t}\n-\n \tif (argc == 2 && !strcmp(argv[1], \"-h\"))\n \t\tusage_with_options(builtin_rebase_usage,\n \t\t\t\t   builtin_rebase_options);\n@@ -1169,6 +1136,11 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \n \tgit_config(rebase_config, &options);\n \n+\tif (options.use_legacy_rebase ||\n+\t    !git_env_bool(\"GIT_TEST_REBASE_USE_BUILTIN\", -1))\n+\t\twarning(_(\"the rebase.useBuiltin support has been removed!\\n\"\n+\t\t\t  \"See its entry in 'git help config' for details.\"));\n+\n \tstrbuf_reset(&buf);\n \tstrbuf_addf(&buf, \"%s/applying\", apply_dir());\n \tif(file_exists(buf.buf))\ndiff --git a/git-legacy-rebase.sh b/git-legacy-rebase.sh\ndeleted file mode 100755\nindex 5c2c4e5276..0000000000\n--- a/git-legacy-rebase.sh\n+++ /dev/null\n@@ -1,770 +0,0 @@\n-#!/bin/sh\n-#\n-# Copyright (c) 2005 Junio C Hamano.\n-#\n-\n-SUBDIRECTORY_OK=Yes\n-OPTIONS_KEEPDASHDASH=\n-OPTIONS_STUCKLONG=t\n-OPTIONS_SPEC=\"\\\n-git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] [<upstream>] [<branch>]\n-git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] --root [<branch>]\n-git rebase --continue | --abort | --skip | --edit-todo\n---\n- Available options are\n-v,verbose!         display a diffstat of what changed upstream\n-q,quiet!           be quiet. implies --no-stat\n-autostash          automatically stash/stash pop before and after\n-fork-point         use 'merge-base --fork-point' to refine upstream\n-onto=!             rebase onto given branch instead of upstream\n-r,rebase-merges?   try to rebase merges instead of skipping them\n-p,preserve-merges! try to recreate merges instead of ignoring them\n-s,strategy=!       use the given merge strategy\n-X,strategy-option=! pass the argument through to the merge strategy\n-no-ff!             cherry-pick all commits, even if unchanged\n-f,force-rebase!    cherry-pick all commits, even if unchanged\n-m,merge!           use merging strategies to rebase\n-i,interactive!     let the user edit the list of commits to rebase\n-x,exec=!           add exec lines after each commit of the editable list\n-k,keep-empty\t   preserve empty commits during rebase\n-allow-empty-message allow rebasing commits with empty messages\n-stat!              display a diffstat of what changed upstream\n-n,no-stat!         do not show diffstat of what changed upstream\n-verify             allow pre-rebase hook to run\n-rerere-autoupdate  allow rerere to update index with resolved conflicts\n-root!              rebase all reachable commits up to the root(s)\n-autosquash         move commits that begin with squash!/fixup! under -i\n-signoff            add a Signed-off-by: line to each commit\n-committer-date-is-author-date! passed to 'git am'\n-ignore-date!       passed to 'git am'\n-whitespace=!       passed to 'git apply'\n-ignore-whitespace! passed to 'git apply'\n-C=!                passed to 'git apply'\n-S,gpg-sign?        GPG-sign commits\n- Actions:\n-continue!          continue\n-abort!             abort and check out the original branch\n-skip!              skip current patch and continue\n-edit-todo!         edit the todo list during an interactive rebase\n-quit!              abort but keep HEAD where it is\n-show-current-patch! show the patch file being applied or merged\n-reschedule-failed-exec automatically reschedule failed exec commands\n-\"\n-. git-sh-setup\n-set_reflog_action rebase\n-require_work_tree_exists\n-cd_to_toplevel\n-\n-LF='\n-'\n-ok_to_skip_pre_rebase=\n-\n-squash_onto=\n-unset onto\n-unset restrict_revision\n-cmd=\n-strategy=\n-strategy_opts=\n-do_merge=\n-merge_dir=\"$GIT_DIR\"/rebase-merge\n-apply_dir=\"$GIT_DIR\"/rebase-apply\n-verbose=\n-diffstat=\n-test \"$(git config --bool rebase.stat)\" = true && diffstat=t\n-autostash=\"$(git config --bool rebase.autostash || echo false)\"\n-fork_point=auto\n-git_am_opt=\n-git_format_patch_opt=\n-rebase_root=\n-force_rebase=\n-allow_rerere_autoupdate=\n-# Non-empty if a rebase was in progress when 'git rebase' was invoked\n-in_progress=\n-# One of {am, merge, interactive}\n-type=\n-# One of {\"$GIT_DIR\"/rebase-apply, \"$GIT_DIR\"/rebase-merge}\n-state_dir=\n-# One of {'', continue, skip, abort}, as parsed from command line\n-action=\n-rebase_merges=\n-rebase_cousins=\n-preserve_merges=\n-autosquash=\n-keep_empty=\n-allow_empty_message=--allow-empty-message\n-signoff=\n-reschedule_failed_exec=\n-test \"$(git config --bool rebase.autosquash)\" = \"true\" && autosquash=t\n-case \"$(git config --bool commit.gpgsign)\" in\n-true)\tgpg_sign_opt=-S ;;\n-*)\tgpg_sign_opt= ;;\n-esac\n-test \"$(git config --bool rebase.reschedulefailedexec)\" = \"true\" &&\n-reschedule_failed_exec=--reschedule-failed-exec\n-. git-rebase--common\n-\n-read_basic_state () {\n-\ttest -f \"$state_dir/head-name\" &&\n-\ttest -f \"$state_dir/onto\" &&\n-\thead_name=$(cat \"$state_dir\"/head-name) &&\n-\tonto=$(cat \"$state_dir\"/onto) &&\n-\t# We always write to orig-head, but interactive rebase used to write to\n-\t# head. Fall back to reading from head to cover for the case that the\n-\t# user upgraded git with an ongoing interactive rebase.\n-\tif test -f \"$state_dir\"/orig-head\n-\tthen\n-\t\torig_head=$(cat \"$state_dir\"/orig-head)\n-\telse\n-\t\torig_head=$(cat \"$state_dir\"/head)\n-\tfi &&\n-\ttest -f \"$state_dir\"/quiet && GIT_QUIET=t\n-\ttest -f \"$state_dir\"/verbose && verbose=t\n-\ttest -f \"$state_dir\"/strategy && strategy=\"$(cat \"$state_dir\"/strategy)\"\n-\ttest -f \"$state_dir\"/strategy_opts &&\n-\t\tstrategy_opts=\"$(cat \"$state_dir\"/strategy_opts)\"\n-\ttest -f \"$state_dir\"/allow_rerere_autoupdate &&\n-\t\tallow_rerere_autoupdate=\"$(cat \"$state_dir\"/allow_rerere_autoupdate)\"\n-\ttest -f \"$state_dir\"/gpg_sign_opt &&\n-\t\tgpg_sign_opt=\"$(cat \"$state_dir\"/gpg_sign_opt)\"\n-\ttest -f \"$state_dir\"/signoff && {\n-\t\tsignoff=\"$(cat \"$state_dir\"/signoff)\"\n-\t\tforce_rebase=t\n-\t}\n-\ttest -f \"$state_dir\"/reschedule-failed-exec &&\n-\t\treschedule_failed_exec=t\n-}\n-\n-finish_rebase () {\n-\trm -f \"$(git rev-parse --git-path REBASE_HEAD)\"\n-\tapply_autostash &&\n-\t{ git gc --auto || true; } &&\n-\trm -rf \"$state_dir\"\n-}\n-\n-run_interactive () {\n-\tGIT_CHERRY_PICK_HELP=\"$resolvemsg\"\n-\texport GIT_CHERRY_PICK_HELP\n-\n-\ttest -n \"$keep_empty\" && keep_empty=\"--keep-empty\"\n-\ttest -n \"$rebase_merges\" && rebase_merges=\"--rebase-merges\"\n-\ttest -n \"$rebase_cousins\" && rebase_cousins=\"--rebase-cousins\"\n-\ttest -n \"$autosquash\" && autosquash=\"--autosquash\"\n-\ttest -n \"$verbose\" && verbose=\"--verbose\"\n-\ttest -n \"$force_rebase\" && force_rebase=\"--no-ff\"\n-\ttest -n \"$restrict_revision\" && \\\n-\t\trestrict_revision=\"--restrict-revision=^$restrict_revision\"\n-\ttest -n \"$upstream\" && upstream=\"--upstream=$upstream\"\n-\ttest -n \"$onto\" && onto=\"--onto=$onto\"\n-\ttest -n \"$squash_onto\" && squash_onto=\"--squash-onto=$squash_onto\"\n-\ttest -n \"$onto_name\" && onto_name=\"--onto-name=$onto_name\"\n-\ttest -n \"$head_name\" && head_name=\"--head-name=$head_name\"\n-\ttest -n \"$strategy\" && strategy=\"--strategy=$strategy\"\n-\ttest -n \"$strategy_opts\" && strategy_opts=\"--strategy-opts=$strategy_opts\"\n-\ttest -n \"$switch_to\" && switch_to=\"--switch-to=$switch_to\"\n-\ttest -n \"$cmd\" && cmd=\"--cmd=$cmd\"\n-\ttest -n \"$action\" && action=\"--$action\"\n-\n-\texec git rebase--interactive \"$action\" \"$keep_empty\" \"$rebase_merges\" \"$rebase_cousins\" \\\n-\t\t\"$upstream\" \"$onto\" \"$squash_onto\" \"$restrict_revision\" \\\n-\t\t\"$allow_empty_message\" \"$autosquash\" \"$verbose\" \\\n-\t\t\"$force_rebase\" \"$onto_name\" \"$head_name\" \"$strategy\" \\\n-\t\t\"$strategy_opts\" \"$cmd\" \"$switch_to\" \\\n-\t\t\"$allow_rerere_autoupdate\" \"$gpg_sign_opt\" \"$signoff\" \\\n-\t\t\"$reschedule_failed_exec\"\n-}\n-\n-run_specific_rebase () {\n-\tif [ \"$interactive_rebase\" = implied ]; then\n-\t\tGIT_SEQUENCE_EDITOR=:\n-\t\texport GIT_SEQUENCE_EDITOR\n-\t\tautosquash=\n-\tfi\n-\n-\tif test -n \"$interactive_rebase\" -a -z \"$preserve_merges\"\n-\tthen\n-\t\trun_interactive\n-\telse\n-\t\t. git-rebase--$type\n-\n-\t\tif test -z \"$preserve_merges\"\n-\t\tthen\n-\t\t\tgit_rebase__$type\n-\t\telse\n-\t\t\tgit_rebase__preserve_merges\n-\t\tfi\n-\tfi\n-\n-\tret=$?\n-\tif test $ret -eq 0\n-\tthen\n-\t\tfinish_rebase\n-\telif test $ret -eq 2 # special exit status for rebase -p\n-\tthen\n-\t\tapply_autostash &&\n-\t\trm -rf \"$state_dir\" &&\n-\t\tdie \"Nothing to do\"\n-\tfi\n-\texit $ret\n-}\n-\n-run_pre_rebase_hook () {\n-\tif test -z \"$ok_to_skip_pre_rebase\" &&\n-\t   test -x \"$(git rev-parse --git-path hooks/pre-rebase)\"\n-\tthen\n-\t\t\"$(git rev-parse --git-path hooks/pre-rebase)\" ${1+\"$@\"} ||\n-\t\tdie \"$(gettext \"The pre-rebase hook refused to rebase.\")\"\n-\tfi\n-}\n-\n-test -f \"$apply_dir\"/applying &&\n-\tdie \"$(gettext \"It looks like 'git am' is in progress. Cannot rebase.\")\"\n-\n-if test -d \"$apply_dir\"\n-then\n-\ttype=am\n-\tstate_dir=\"$apply_dir\"\n-elif test -d \"$merge_dir\"\n-then\n-\ttype=interactive\n-\tif test -d \"$merge_dir\"/rewritten\n-\tthen\n-\t\ttype=preserve-merges\n-\t\tinteractive_rebase=explicit\n-\t\tpreserve_merges=t\n-\telif test -f \"$merge_dir\"/interactive\n-\tthen\n-\t\tinteractive_rebase=explicit\n-\tfi\n-\tstate_dir=\"$merge_dir\"\n-fi\n-test -n \"$type\" && in_progress=t\n-\n-total_argc=$#\n-while test $# != 0\n-do\n-\tcase \"$1\" in\n-\t--no-verify)\n-\t\tok_to_skip_pre_rebase=yes\n-\t\t;;\n-\t--verify)\n-\t\tok_to_skip_pre_rebase=\n-\t\t;;\n-\t--continue|--skip|--abort|--quit|--edit-todo|--show-current-patch)\n-\t\ttest $total_argc -eq 2 || usage\n-\t\taction=${1##--}\n-\t\t;;\n-\t--onto=*)\n-\t\tonto=\"${1#--onto=}\"\n-\t\t;;\n-\t--exec=*)\n-\t\tcmd=\"${cmd}exec ${1#--exec=}${LF}\"\n-\t\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n-\t\t;;\n-\t--interactive)\n-\t\tinteractive_rebase=explicit\n-\t\t;;\n-\t--keep-empty)\n-\t\tkeep_empty=yes\n-\t\t;;\n-\t--allow-empty-message)\n-\t\tallow_empty_message=--allow-empty-message\n-\t\t;;\n-\t--no-keep-empty)\n-\t\tkeep_empty=\n-\t\t;;\n-\t--rebase-merges)\n-\t\trebase_merges=t\n-\t\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n-\t\t;;\n-\t--rebase-merges=*)\n-\t\trebase_merges=t\n-\t\tcase \"${1#*=}\" in\n-\t\trebase-cousins) rebase_cousins=t;;\n-\t\tno-rebase-cousins) rebase_cousins=;;\n-\t\t*) die \"Unknown mode: $1\";;\n-\t\tesac\n-\t\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n-\t\t;;\n-\t--preserve-merges)\n-\t\tpreserve_merges=t\n-\t\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n-\t\t;;\n-\t--autosquash)\n-\t\tautosquash=t\n-\t\t;;\n-\t--no-autosquash)\n-\t\tautosquash=\n-\t\t;;\n-\t--fork-point)\n-\t\tfork_point=t\n-\t\t;;\n-\t--no-fork-point)\n-\t\tfork_point=\n-\t\t;;\n-\t--merge)\n-\t\tdo_merge=t\n-\t\t;;\n-\t--strategy-option=*)\n-\t\tstrategy_opts=\"$strategy_opts $(git rev-parse --sq-quote \"--${1#--strategy-option=}\" | sed -e s/^.//)\"\n-\t\tdo_merge=t\n-\t\ttest -z \"$strategy\" && strategy=recursive\n-\t\t;;\n-\t--strategy=*)\n-\t\tstrategy=\"${1#--strategy=}\"\n-\t\tdo_merge=t\n-\t\t;;\n-\t--no-stat)\n-\t\tdiffstat=\n-\t\t;;\n-\t--stat)\n-\t\tdiffstat=t\n-\t\t;;\n-\t--autostash)\n-\t\tautostash=true\n-\t\t;;\n-\t--no-autostash)\n-\t\tautostash=false\n-\t\t;;\n-\t--verbose)\n-\t\tverbose=t\n-\t\tdiffstat=t\n-\t\tGIT_QUIET=\n-\t\t;;\n-\t--quiet)\n-\t\tGIT_QUIET=t\n-\t\tgit_am_opt=\"$git_am_opt -q\"\n-\t\tverbose=\n-\t\tdiffstat=\n-\t\t;;\n-\t--whitespace=*)\n-\t\tgit_am_opt=\"$git_am_opt --whitespace=${1#--whitespace=}\"\n-\t\tcase \"${1#--whitespace=}\" in\n-\t\tfix|strip)\n-\t\t\tforce_rebase=t\n-\t\t\t;;\n-\t\twarn|nowarn|error|error-all)\n-\t\t\t;; # okay, known whitespace option\n-\t\t*)\n-\t\t\tdie \"fatal: Invalid whitespace option: '${1#*=}'\"\n-\t\t\t;;\n-\t\tesac\n-\t\t;;\n-\t--ignore-whitespace)\n-\t\tgit_am_opt=\"$git_am_opt $1\"\n-\t\t;;\n-\t--signoff)\n-\t\tsignoff=--signoff\n-\t\t;;\n-\t--no-signoff)\n-\t\tsignoff=\n-\t\t;;\n-\t--committer-date-is-author-date|--ignore-date)\n-\t\tgit_am_opt=\"$git_am_opt $1\"\n-\t\tforce_rebase=t\n-\t\t;;\n-\t-C*[!0-9]*)\n-\t\tdie \"fatal: switch \\`C' expects a numerical value\"\n-\t\t;;\n-\t-C*)\n-\t\tgit_am_opt=\"$git_am_opt $1\"\n-\t\t;;\n-\t--root)\n-\t\trebase_root=t\n-\t\t;;\n-\t--force-rebase|--no-ff)\n-\t\tforce_rebase=t\n-\t\t;;\n-\t--rerere-autoupdate|--no-rerere-autoupdate)\n-\t\tallow_rerere_autoupdate=\"$1\"\n-\t\t;;\n-\t--gpg-sign)\n-\t\tgpg_sign_opt=-S\n-\t\t;;\n-\t--gpg-sign=*)\n-\t\tgpg_sign_opt=\"-S${1#--gpg-sign=}\"\n-\t\t;;\n-\t--reschedule-failed-exec)\n-\t\treschedule_failed_exec=--reschedule-failed-exec\n-\t\t;;\n-\t--no-reschedule-failed-exec)\n-\t\treschedule_failed_exec=\n-\t\t;;\n-\t--)\n-\t\tshift\n-\t\tbreak\n-\t\t;;\n-\t*)\n-\t\tusage\n-\t\t;;\n-\tesac\n-\tshift\n-done\n-test $# -gt 2 && usage\n-\n-if test -n \"$action\"\n-then\n-\ttest -z \"$in_progress\" && die \"$(gettext \"No rebase in progress?\")\"\n-\t# Only interactive rebase uses detailed reflog messages\n-\tif test -n \"$interactive_rebase\" && test \"$GIT_REFLOG_ACTION\" = rebase\n-\tthen\n-\t\tGIT_REFLOG_ACTION=\"rebase -i ($action)\"\n-\t\texport GIT_REFLOG_ACTION\n-\tfi\n-fi\n-\n-if test \"$action\" = \"edit-todo\" && test -z \"$interactive_rebase\"\n-then\n-\tdie \"$(gettext \"The --edit-todo action can only be used during interactive rebase.\")\"\n-fi\n-\n-case \"$action\" in\n-continue)\n-\t# Sanity check\n-\tgit rev-parse --verify HEAD >/dev/null ||\n-\t\tdie \"$(gettext \"Cannot read HEAD\")\"\n-\tgit update-index --ignore-submodules --refresh &&\n-\tgit diff-files --quiet --ignore-submodules || {\n-\t\techo \"$(gettext \"You must edit all merge conflicts and then\n-mark them as resolved using git add\")\"\n-\t\texit 1\n-\t}\n-\tread_basic_state\n-\trun_specific_rebase\n-\t;;\n-skip)\n-\toutput git reset --hard HEAD || exit $?\n-\tread_basic_state\n-\trun_specific_rebase\n-\t;;\n-abort)\n-\tgit rerere clear\n-\tread_basic_state\n-\tcase \"$head_name\" in\n-\trefs/*)\n-\t\tgit symbolic-ref -m \"rebase: aborting\" HEAD $head_name ||\n-\t\tdie \"$(eval_gettext \"Could not move back to \\$head_name\")\"\n-\t\t;;\n-\tesac\n-\toutput git reset --hard $orig_head\n-\tfinish_rebase\n-\texit\n-\t;;\n-quit)\n-\texec rm -rf \"$state_dir\"\n-\t;;\n-edit-todo)\n-\trun_specific_rebase\n-\t;;\n-show-current-patch)\n-\trun_specific_rebase\n-\tdie \"BUG: run_specific_rebase is not supposed to return here\"\n-\t;;\n-esac\n-\n-# Make sure no rebase is in progress\n-if test -n \"$in_progress\"\n-then\n-\tstate_dir_base=${state_dir##*/}\n-\tcmd_live_rebase=\"git rebase (--continue | --abort | --skip)\"\n-\tcmd_clear_stale_rebase=\"rm -fr \\\"$state_dir\\\"\"\n-\tdie \"\n-$(eval_gettext 'It seems that there is already a $state_dir_base directory, and\n-I wonder if you are in the middle of another rebase.  If that is the\n-case, please try\n-\t$cmd_live_rebase\n-If that is not the case, please\n-\t$cmd_clear_stale_rebase\n-and run me again.  I am stopping in case you still have something\n-valuable there.')\"\n-fi\n-\n-if test -n \"$rebase_root\" && test -z \"$onto\"\n-then\n-\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n-fi\n-\n-if test -n \"$keep_empty\"\n-then\n-\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n-fi\n-\n-actually_interactive=\n-if test -n \"$interactive_rebase\"\n-then\n-\tif test -z \"$preserve_merges\"\n-\tthen\n-\t\ttype=interactive\n-\telse\n-\t\ttype=preserve-merges\n-\tfi\n-\tactually_interactive=t\n-\tstate_dir=\"$merge_dir\"\n-elif test -n \"$do_merge\"\n-then\n-\tinteractive_rebase=implied\n-\ttype=interactive\n-\tstate_dir=\"$merge_dir\"\n-else\n-\ttype=am\n-\tstate_dir=\"$apply_dir\"\n-fi\n-\n-if test -t 2 && test -z \"$GIT_QUIET\"\n-then\n-\tgit_format_patch_opt=\"$git_format_patch_opt --progress\"\n-fi\n-\n-incompatible_opts=$(echo \" $git_am_opt \" | \\\n-\t\t    sed -e 's/ -q / /g' -e 's/^ \\(.*\\) $/\\1/')\n-if test -n \"$incompatible_opts\"\n-then\n-\tif test -n \"$actually_interactive\" || test \"$do_merge\"\n-\tthen\n-\t\tdie \"$(gettext \"fatal: cannot combine am options with either interactive or merge options\")\"\n-\tfi\n-fi\n-\n-if test -n \"$signoff\"\n-then\n-\ttest -n \"$preserve_merges\" &&\n-\t\tdie \"$(gettext \"fatal: cannot combine '--signoff' with '--preserve-merges'\")\"\n-\tgit_am_opt=\"$git_am_opt $signoff\"\n-\tforce_rebase=t\n-fi\n-\n-if test -n \"$preserve_merges\"\n-then\n-\t# Note: incompatibility with --signoff handled in signoff block above\n-\t# Note: incompatibility with --interactive is just a strong warning;\n-\t#       git-rebase.txt caveats with \"unless you know what you are doing\"\n-\ttest -n \"$rebase_merges\" &&\n-\t\tdie \"$(gettext \"fatal: cannot combine '--preserve-merges' with '--rebase-merges'\")\"\n-\n-\ttest -n \"$reschedule_failed_exec\" &&\n-\t\tdie \"$(gettext \"error: cannot combine '--preserve-merges' with '--reschedule-failed-exec'\")\"\n-fi\n-\n-if test -n \"$rebase_merges\"\n-then\n-\ttest -n \"$strategy_opts\" &&\n-\t\tdie \"$(gettext \"fatal: cannot combine '--rebase-merges' with '--strategy-option'\")\"\n-\ttest -n \"$strategy\" &&\n-\t\tdie \"$(gettext \"fatal: cannot combine '--rebase-merges' with '--strategy'\")\"\n-fi\n-\n-if test -z \"$rebase_root\"\n-then\n-\tcase \"$#\" in\n-\t0)\n-\t\tif ! upstream_name=$(git rev-parse --symbolic-full-name \\\n-\t\t\t--verify -q @{upstream} 2>/dev/null)\n-\t\tthen\n-\t\t\t. git-parse-remote\n-\t\t\terror_on_missing_default_upstream \"rebase\" \"rebase\" \\\n-\t\t\t\t\"against\" \"git rebase $(gettext '<branch>')\"\n-\t\tfi\n-\n-\t\ttest \"$fork_point\" = auto && fork_point=t\n-\t\t;;\n-\t*)\tupstream_name=\"$1\"\n-\t\tif test \"$upstream_name\" = \"-\"\n-\t\tthen\n-\t\t\tupstream_name=\"@{-1}\"\n-\t\tfi\n-\t\tshift\n-\t\t;;\n-\tesac\n-\tupstream=$(peel_committish \"${upstream_name}\") ||\n-\tdie \"$(eval_gettext \"invalid upstream '\\$upstream_name'\")\"\n-\tupstream_arg=\"$upstream_name\"\n-else\n-\tif test -z \"$onto\"\n-\tthen\n-\t\tempty_tree=$(git hash-object -t tree /dev/null)\n-\t\tonto=$(git commit-tree $empty_tree </dev/null)\n-\t\tsquash_onto=\"$onto\"\n-\tfi\n-\tunset upstream_name\n-\tunset upstream\n-\ttest $# -gt 1 && usage\n-\tupstream_arg=--root\n-fi\n-\n-# Make sure the branch to rebase onto is valid.\n-onto_name=${onto-\"$upstream_name\"}\n-case \"$onto_name\" in\n-*...*)\n-\tif\tleft=${onto_name%...*} right=${onto_name#*...} &&\n-\t\tonto=$(git merge-base --all ${left:-HEAD} ${right:-HEAD})\n-\tthen\n-\t\tcase \"$onto\" in\n-\t\t?*\"$LF\"?*)\n-\t\t\tdie \"$(eval_gettext \"\\$onto_name: there are more than one merge bases\")\"\n-\t\t\t;;\n-\t\t'')\n-\t\t\tdie \"$(eval_gettext \"\\$onto_name: there is no merge base\")\"\n-\t\t\t;;\n-\t\tesac\n-\telse\n-\t\tdie \"$(eval_gettext \"\\$onto_name: there is no merge base\")\"\n-\tfi\n-\t;;\n-*)\n-\tonto=$(peel_committish \"$onto_name\") ||\n-\tdie \"$(eval_gettext \"Does not point to a valid commit: \\$onto_name\")\"\n-\t;;\n-esac\n-\n-# If the branch to rebase is given, that is the branch we will rebase\n-# $branch_name -- branch/commit being rebased, or HEAD (already detached)\n-# $orig_head -- commit object name of tip of the branch before rebasing\n-# $head_name -- refs/heads/<that-branch> or \"detached HEAD\"\n-switch_to=\n-case \"$#\" in\n-1)\n-\t# Is it \"rebase other $branchname\" or \"rebase other $commit\"?\n-\tbranch_name=\"$1\"\n-\tswitch_to=\"$1\"\n-\n-\t# Is it a local branch?\n-\tif git show-ref --verify --quiet -- \"refs/heads/$branch_name\" &&\n-\t   orig_head=$(git rev-parse -q --verify \"refs/heads/$branch_name\")\n-\tthen\n-\t\thead_name=\"refs/heads/$branch_name\"\n-\t# If not is it a valid ref (branch or commit)?\n-\telif orig_head=$(git rev-parse -q --verify \"$branch_name\")\n-\tthen\n-\t\thead_name=\"detached HEAD\"\n-\n-\telse\n-\t\tdie \"$(eval_gettext \"fatal: no such branch/commit '\\$branch_name'\")\"\n-\tfi\n-\t;;\n-0)\n-\t# Do not need to switch branches, we are already on it.\n-\tif branch_name=$(git symbolic-ref -q HEAD)\n-\tthen\n-\t\thead_name=$branch_name\n-\t\tbranch_name=$(expr \"z$branch_name\" : 'zrefs/heads/\\(.*\\)')\n-\telse\n-\t\thead_name=\"detached HEAD\"\n-\t\tbranch_name=HEAD\n-\tfi\n-\torig_head=$(git rev-parse --verify HEAD) || exit\n-\t;;\n-*)\n-\tdie \"BUG: unexpected number of arguments left to parse\"\n-\t;;\n-esac\n-\n-if test \"$fork_point\" = t\n-then\n-\tnew_upstream=$(git merge-base --fork-point \"$upstream_name\" \\\n-\t\t\t\"${switch_to:-HEAD}\")\n-\tif test -n \"$new_upstream\"\n-\tthen\n-\t\trestrict_revision=$new_upstream\n-\tfi\n-fi\n-\n-if test \"$autostash\" = true && ! (require_clean_work_tree) 2>/dev/null\n-then\n-\tstash_sha1=$(git stash create \"autostash\") ||\n-\tdie \"$(gettext 'Cannot autostash')\"\n-\n-\tmkdir -p \"$state_dir\" &&\n-\techo $stash_sha1 >\"$state_dir/autostash\" &&\n-\tstash_abbrev=$(git rev-parse --short $stash_sha1) &&\n-\techo \"$(eval_gettext 'Created autostash: $stash_abbrev')\" &&\n-\tgit reset --hard\n-fi\n-\n-require_clean_work_tree \"rebase\" \"$(gettext \"Please commit or stash them.\")\"\n-\n-# Now we are rebasing commits $upstream..$orig_head (or with --root,\n-# everything leading up to $orig_head) on top of $onto\n-\n-# Check if we are already based on $onto with linear history,\n-# but this should be done only when upstream and onto are the same\n-# and if this is not an interactive rebase.\n-mb=$(git merge-base \"$onto\" \"$orig_head\")\n-if test -z \"$actually_interactive\" && test \"$upstream\" = \"$onto\" &&\n-\ttest \"$mb\" = \"$onto\" && test -z \"$restrict_revision\" &&\n-\t# linear history?\n-\t! (git rev-list --parents \"$onto\"..\"$orig_head\" | sane_grep \" .* \") > /dev/null\n-then\n-\tif test -z \"$force_rebase\"\n-\tthen\n-\t\t# Lazily switch to the target branch if needed...\n-\t\ttest -z \"$switch_to\" ||\n-\t\tGIT_REFLOG_ACTION=\"$GIT_REFLOG_ACTION: checkout $switch_to\" \\\n-\t\t\tgit checkout -q \"$switch_to\" --\n-\t\tif test \"$branch_name\" = \"HEAD\" &&\n-\t\t\t ! git symbolic-ref -q HEAD\n-\t\tthen\n-\t\t\tsay \"$(eval_gettext \"HEAD is up to date.\")\"\n-\t\telse\n-\t\t\tsay \"$(eval_gettext \"Current branch \\$branch_name is up to date.\")\"\n-\t\tfi\n-\t\tfinish_rebase\n-\t\texit 0\n-\telse\n-\t\tif test \"$branch_name\" = \"HEAD\" &&\n-\t\t\t ! git symbolic-ref -q HEAD\n-\t\tthen\n-\t\t\tsay \"$(eval_gettext \"HEAD is up to date, rebase forced.\")\"\n-\t\telse\n-\t\t\tsay \"$(eval_gettext \"Current branch \\$branch_name is up to date, rebase forced.\")\"\n-\t\tfi\n-\tfi\n-fi\n-\n-# If a hook exists, give it a chance to interrupt\n-run_pre_rebase_hook \"$upstream_arg\" \"$@\"\n-\n-if test -n \"$diffstat\"\n-then\n-\tif test -n \"$verbose\"\n-\tthen\n-\t\tif test -z \"$mb\"\n-\t\tthen\n-\t\t\techo \"$(eval_gettext \"Changes to \\$onto:\")\"\n-\t\telse\n-\t\t\techo \"$(eval_gettext \"Changes from \\$mb to \\$onto:\")\"\n-\t\tfi\n-\tfi\n-\tmb_tree=\"${mb:-$(git hash-object -t tree /dev/null)}\"\n-\t# We want color (if set), but no pager\n-\tGIT_PAGER='' git diff --stat --summary \"$mb_tree\" \"$onto\"\n-fi\n-\n-if test -z \"$actually_interactive\" && test \"$mb\" = \"$orig_head\"\n-then\n-\tsay \"$(eval_gettext \"Fast-forwarded \\$branch_name to \\$onto_name.\")\"\n-\tGIT_REFLOG_ACTION=\"$GIT_REFLOG_ACTION: checkout $onto_name\" \\\n-\t\tgit checkout -q \"$onto^0\" || die \"could not detach HEAD\"\n-\t# If the $onto is a proper descendant of the tip of the branch, then\n-\t# we just fast-forwarded.\n-\tgit update-ref ORIG_HEAD $orig_head\n-\tmove_to_original_branch\n-\tfinish_rebase\n-\texit 0\n-fi\n-\n-test -n \"$interactive_rebase\" && run_specific_rebase\n-\n-# Detach HEAD and reset the tree\n-say \"$(gettext \"First, rewinding head to replay your work on top of it...\")\"\n-\n-GIT_REFLOG_ACTION=\"$GIT_REFLOG_ACTION: checkout $onto_name\" \\\n-\tgit checkout -q \"$onto^0\" || die \"could not detach HEAD\"\n-git update-ref ORIG_HEAD $orig_head\n-\n-if test -n \"$rebase_root\"\n-then\n-\trevisions=\"$onto..$orig_head\"\n-else\n-\trevisions=\"${restrict_revision-$upstream}..$orig_head\"\n-fi\n-\n-run_specific_rebase\ndiff --git a/t/README b/t/README\nindex 7a3d582267..385262357b 100644\n--- a/t/README\n+++ b/t/README\n@@ -379,10 +379,6 @@ the --no-sparse command-line argument.\n GIT_TEST_PRELOAD_INDEX=<boolean> exercises the preload-index code path\n by overriding the minimum number of cache entries required per thread.\n \n-GIT_TEST_REBASE_USE_BUILTIN=<boolean>, when false, disables the\n-builtin version of git-rebase. See 'rebase.useBuiltin' in\n-git-config(1).\n-\n GIT_TEST_INDEX_THREADS=<n> enables exercising the multi-threaded loading\n of the index for the whole test suite by bypassing the default number of\n cache entries and thread minimums. Setting this to 1 will make the\ndiff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh\nindex 3e73f7584c..a809de9304 100755\n--- a/t/t3400-rebase.sh\n+++ b/t/t3400-rebase.sh\n@@ -311,4 +311,20 @@ test_expect_success 'rebase--merge.sh and --show-current-patch' '\n \t)\n '\n \n+test_expect_success 'rebase -c rebase.useBuiltin=false warning' '\n+\texpected=\"rebase.useBuiltin support has been removed\" &&\n+\n+\t# Only warn when the legacy rebase is requested...\n+\ttest_must_fail git -c rebase.useBuiltin=false rebase 2>err &&\n+\ttest_i18ngrep \"$expected\" err &&\n+\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=false git rebase 2>err &&\n+\ttest_i18ngrep \"$expected\" err &&\n+\n+\t# ...not when we would have used the built-in anyway\n+\ttest_must_fail git -c rebase.useBuiltin=true rebase 2>err &&\n+\ttest_must_be_empty err &&\n+\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=true git rebase 2>err &&\n+\ttest_must_be_empty err\n+'\n+\n test_done\ndiff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\nindex b60b11f9f2..1723e1a858 100755\n--- a/t/t3404-rebase-interactive.sh\n+++ b/t/t3404-rebase-interactive.sh\n@@ -149,12 +149,10 @@ test_expect_success 'rebase -i with the exec command checks tree cleanness' '\n \n test_expect_success 'rebase -x with empty command fails' '\n \ttest_when_finished \"git rebase --abort ||:\" &&\n-\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=true \\\n-\t\tgit rebase -x \"\" @ 2>actual &&\n+\ttest_must_fail env git rebase -x \"\" @ 2>actual &&\n \ttest_write_lines \"error: empty exec command\" >expected &&\n \ttest_i18ncmp expected actual &&\n-\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=true \\\n-\t\tgit rebase -x \" \" @ 2>actual &&\n+\ttest_must_fail env git rebase -x \" \" @ 2>actual &&\n \ttest_i18ncmp expected actual\n '\n \n@@ -162,8 +160,7 @@ LF='\n '\n test_expect_success 'rebase -x with newline in command fails' '\n \ttest_when_finished \"git rebase --abort ||:\" &&\n-\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=true \\\n-\t\tgit rebase -x \"a${LF}b\" @ 2>actual &&\n+\ttest_must_fail env git rebase -x \"a${LF}b\" @ 2>actual &&\n \ttest_write_lines \"error: exec commands cannot contain newlines\" \\\n \t\t\t >expected &&\n \ttest_i18ncmp expected actual\n-- \n2.21.0.360.g471c308f928\n\n"},{"id":"371597","messageId":"nycvar.QRO.7.76.6.1903151643300.41@tvgsbejvaqbjf.bet","threadId":"50341","inReplyTo":"20190315134548.24479-1-avarab@gmail.com","subject":"Re: [PATCH v3] rebase: remove the rebase.useBuiltin setting","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2019-03-15T15:44:04Z","receivedAt":"2019-03-15T15:44:29Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Ævar,\n\nOn Fri, 15 Mar 2019, Ævar Arnfjörð Bjarmason wrote:\n\n> Remove the rebase.useBuiltin setting, which was added as an escape\n> hatch to disable the builtin version of rebase first released with Git\n> 2.20.\n> \n> See [1] for the initial implementation of rebase.useBuiltin, and [2]\n> and [3] for the documentation and corresponding\n> GIT_TEST_REBASE_USE_BUILTIN option.\n> \n> Carrying the legacy version is a maintenance burden as seen in\n> 7e097e27d3 (\"legacy-rebase: backport -C<n> and --whitespace=<option>\n> checks\", 2018-11-20) and 9aea5e9286 (\"rebase: fix regression in\n> rebase.useBuiltin=false test mode\", 2019-02-13). Since the built-in\n> version has been shown to be stable enough let's remove the legacy\n> version.\n> \n> As noted in [3] having use_builtin_rebase() shell out to get its\n> config doesn't make any sense anymore, that was done for the purposes\n> of spawning the legacy rebase without having modified any global\n> state. Let's instead handle this case in rebase_config().\n> \n> There's still a bunch of references to git-legacy-rebase in po/*.po,\n> but those will be dealt with in time by the i18n effort.\n> \n> Even though this configuration variable only existed for one release\n> let's not entirely delete the entry from the docs, but note its\n> absence. Individual versions of git tend to be around for a while due\n> to distro packaging timelines, so e.g. if we're \"lucky\" a given\n> version like 2.21 might be installed on say OSX for half a decade.\n> \n> That'll mean some people probably setting this in config, and then\n> when they later wonder if it's needed they can Google search the\n> config option name or check it in git-config. It also allows us to\n> refer to the docs from the warning for details.\n> \n> 1. 55071ea248 (\"rebase: start implementing it as a builtin\",\n>    2018-08-07)\n> 2. d8d0a546f0 (\"rebase doc: document rebase.useBuiltin\", 2018-11-14)\n> 3. 62c23938fa (\"tests: add a special setup where rebase.useBuiltin is\n>    off\", 2018-11-14)\n> 3. https://public-inbox.org/git/nycvar.QRO.7.76.6.1903141544110.41@tvgsbejvaqbjf.bet/\n> ---\n\nWith the obviously intended SOB line: ACK!\n\nCiao,\nDscho"},{"id":"371612","messageId":"87wol09kxv.fsf@evledraar.gmail.com","threadId":"50341","inReplyTo":"nycvar.QRO.7.76.6.1903151643300.41@tvgsbejvaqbjf.bet","subject":"Re: [PATCH v3] rebase: remove the rebase.useBuiltin setting","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2019-03-15T16:11:40Z","receivedAt":"2019-03-15T16:11:45Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Fri, Mar 15 2019, Johannes Schindelin wrote:\n\n> Hi Ævar,\n>\n> On Fri, 15 Mar 2019, Ævar Arnfjörð Bjarmason wrote:\n>\n>> Remove the rebase.useBuiltin setting, which was added as an escape\n>> hatch to disable the builtin version of rebase first released with Git\n>> 2.20.\n>>\n>> See [1] for the initial implementation of rebase.useBuiltin, and [2]\n>> and [3] for the documentation and corresponding\n>> GIT_TEST_REBASE_USE_BUILTIN option.\n>>\n>> Carrying the legacy version is a maintenance burden as seen in\n>> 7e097e27d3 (\"legacy-rebase: backport -C<n> and --whitespace=<option>\n>> checks\", 2018-11-20) and 9aea5e9286 (\"rebase: fix regression in\n>> rebase.useBuiltin=false test mode\", 2019-02-13). Since the built-in\n>> version has been shown to be stable enough let's remove the legacy\n>> version.\n>>\n>> As noted in [3] having use_builtin_rebase() shell out to get its\n>> config doesn't make any sense anymore, that was done for the purposes\n>> of spawning the legacy rebase without having modified any global\n>> state. Let's instead handle this case in rebase_config().\n>>\n>> There's still a bunch of references to git-legacy-rebase in po/*.po,\n>> but those will be dealt with in time by the i18n effort.\n>>\n>> Even though this configuration variable only existed for one release\n>> let's not entirely delete the entry from the docs, but note its\n>> absence. Individual versions of git tend to be around for a while due\n>> to distro packaging timelines, so e.g. if we're \"lucky\" a given\n>> version like 2.21 might be installed on say OSX for half a decade.\n>>\n>> That'll mean some people probably setting this in config, and then\n>> when they later wonder if it's needed they can Google search the\n>> config option name or check it in git-config. It also allows us to\n>> refer to the docs from the warning for details.\n>>\n>> 1. 55071ea248 (\"rebase: start implementing it as a builtin\",\n>>    2018-08-07)\n>> 2. d8d0a546f0 (\"rebase doc: document rebase.useBuiltin\", 2018-11-14)\n>> 3. 62c23938fa (\"tests: add a special setup where rebase.useBuiltin is\n>>    off\", 2018-11-14)\n>> 3. https://public-inbox.org/git/nycvar.QRO.7.76.6.1903141544110.41@tvgsbejvaqbjf.bet/\n>> ---\n>\n> With the obviously intended SOB line: ACK!\n\nUrgh, Junio: If there's no other comments/concerns on v3 requiring a v4\nthis has my:\n\n    Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n"},{"id":"371778","messageId":"xmqqwokw3eei.fsf@gitster-ct.c.googlers.com","threadId":"50341","inReplyTo":"87wol09kxv.fsf@evledraar.gmail.com","subject":"Re: [PATCH v3] rebase: remove the rebase.useBuiltin setting","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-03-18T06:06:13Z","receivedAt":"2019-03-18T06:06:17Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:\n\n> Urgh, Junio: If there's no other comments/concerns on v3 requiring a v4\n> this has my:\n>\n>     Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n\nAlright.  Let's queue, wait for a while to see if there is anything\nelse and continue.\n\nThanks.\n"},{"id":"371801","messageId":"8b912120-d9c9-be6c-d7ac-dd4036d3100f@gmail.com","threadId":"50341","inReplyTo":"20190315134548.24479-1-avarab@gmail.com","subject":"Re: [PATCH v3] rebase: remove the rebase.useBuiltin setting","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2019-03-18T10:19:57Z","receivedAt":"2019-03-18T10:20:06Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Ævar\n\nThanks for doing this, it's great to see it from a maintenance \nperspective as well as it meaning the builtin rebase is considered \nstable. A couple small nit picks below\n\nOn 15/03/2019 13:45, Ævar Arnfjörð Bjarmason wrote:\n> Remove the rebase.useBuiltin setting, which was added as an escape\n> hatch to disable the builtin version of rebase first released with Git\n> 2.20.\n> \n> See [1] for the initial implementation of rebase.useBuiltin, and [2]\n> and [3] for the documentation and corresponding\n> GIT_TEST_REBASE_USE_BUILTIN option.\n> \n> Carrying the legacy version is a maintenance burden as seen in\n> 7e097e27d3 (\"legacy-rebase: backport -C<n> and --whitespace=<option>\n> checks\", 2018-11-20) and 9aea5e9286 (\"rebase: fix regression in\n> rebase.useBuiltin=false test mode\", 2019-02-13). Since the built-in\n> version has been shown to be stable enough let's remove the legacy\n> version.\n> \n> As noted in [3] having use_builtin_rebase() shell out to get its\n> config doesn't make any sense anymore, that was done for the purposes\n> of spawning the legacy rebase without having modified any global\n> state. Let's instead handle this case in rebase_config().\n> \n> There's still a bunch of references to git-legacy-rebase in po/*.po,\n> but those will be dealt with in time by the i18n effort.\n> \n> Even though this configuration variable only existed for one release\n\nIf it was added in 2.20 then that's two releases isn't it?\n\n> let's not entirely delete the entry from the docs, but note its\n> absence. Individual versions of git tend to be around for a while due\n> to distro packaging timelines, so e.g. if we're \"lucky\" a given\n> version like 2.21 might be installed on say OSX for half a decade.\n> \n> That'll mean some people probably setting this in config, and then\n> when they later wonder if it's needed they can Google search the\n> config option name or check it in git-config. It also allows us to\n> refer to the docs from the warning for details.\n> \n> 1. 55071ea248 (\"rebase: start implementing it as a builtin\",\n>     2018-08-07)\n> 2. d8d0a546f0 (\"rebase doc: document rebase.useBuiltin\", 2018-11-14)\n> 3. 62c23938fa (\"tests: add a special setup where rebase.useBuiltin is\n>     off\", 2018-11-14)\n> 3. https://public-inbox.org/git/nycvar.QRO.7.76.6.1903141544110.41@tvgsbejvaqbjf.bet/\n> ---\n> \n> Addresses Johannes's comments on v2, and improves the tests I'm adding\n> to cover both the env var & config variable.\n> \n>   .gitignore                      |   1 -\n>   Documentation/config/rebase.txt |  17 +-\n>   Makefile                        |   1 -\n>   builtin/rebase.c                |  50 +--\n>   git-legacy-rebase.sh            | 770 --------------------------------\n>   t/README                        |   4 -\n>   t/t3400-rebase.sh               |  16 +\n>   t/t3404-rebase-interactive.sh   |   9 +-\n>   8 files changed, 35 insertions(+), 833 deletions(-)\n>   delete mode 100755 git-legacy-rebase.sh\n> \n> diff --git a/.gitignore b/.gitignore\n> index 7374587f9d..5cb84f1d1a 100644\n> --- a/.gitignore\n> +++ b/.gitignore\n> @@ -82,7 +82,6 @@\n>   /git-init-db\n>   /git-interpret-trailers\n>   /git-instaweb\n> -/git-legacy-rebase\n>   /git-log\n>   /git-ls-files\n>   /git-ls-remote\n> diff --git a/Documentation/config/rebase.txt b/Documentation/config/rebase.txt\n> index 331d250e04..c747452983 100644\n> --- a/Documentation/config/rebase.txt\n> +++ b/Documentation/config/rebase.txt\n> @@ -1,16 +1,9 @@\n>   rebase.useBuiltin::\n> -\tSet to `false` to use the legacy shellscript implementation of\n> -\tlinkgit:git-rebase[1]. Is `true` by default, which means use\n> -\tthe built-in rewrite of it in C.\n> -+\n> -The C rewrite is first included with Git version 2.20. This option\n> -serves an an escape hatch to re-enable the legacy version in case any\n> -bugs are found in the rewrite. This option and the shellscript version\n> -of linkgit:git-rebase[1] will be removed in some future release.\n> -+\n> -If you find some reason to set this option to `false` other than\n> -one-off testing you should report the behavior difference as a bug in\n> -git.\n> +\tUnused configuration variable. Used between Git version 2.20\n> +\tand 2.21\n\nIf it is present in 2.21 then this is perhaps ambiguous, Iread it as < \n2.21 rather than <=2.21 (I just asked my wife what she thought it meant \nto make sure it wasn't just me and she says the same) so maybe\n\nUsed in Git versions 2.20 and 2.21\n\nwould be clearer\n\nBest Wishes\n\nPhillip\n\n  as an escape hatch to enable the legacy shellscript\n> +\timplementation of rebase. Now the built-in rewrite of it in C\n> +\tis always used. Setting this will emit a warning, to alert any\n> +\tremaining users that setting this now does nothing.\n>   \n>   rebase.stat::\n>   \tWhether to show a diffstat of what changed upstream since the last\n> diff --git a/Makefile b/Makefile\n> index 537493822b..9f1159cffc 100644\n> --- a/Makefile\n> +++ b/Makefile\n> @@ -632,7 +632,6 @@ SCRIPT_SH += git-merge-one-file.sh\n>   SCRIPT_SH += git-merge-resolve.sh\n>   SCRIPT_SH += git-mergetool.sh\n>   SCRIPT_SH += git-quiltimport.sh\n> -SCRIPT_SH += git-legacy-rebase.sh\n>   SCRIPT_SH += git-remote-testgit.sh\n>   SCRIPT_SH += git-request-pull.sh\n>   SCRIPT_SH += git-stash.sh\n> diff --git a/builtin/rebase.c b/builtin/rebase.c\n> index 52114cbf0d..bc3dc629c1 100644\n> --- a/builtin/rebase.c\n> +++ b/builtin/rebase.c\n> @@ -46,29 +46,6 @@ enum rebase_type {\n>   \tREBASE_PRESERVE_MERGES\n>   };\n>   \n> -static int use_builtin_rebase(void)\n> -{\n> -\tstruct child_process cp = CHILD_PROCESS_INIT;\n> -\tstruct strbuf out = STRBUF_INIT;\n> -\tint ret, env = git_env_bool(\"GIT_TEST_REBASE_USE_BUILTIN\", -1);\n> -\n> -\tif (env != -1)\n> -\t\treturn env;\n> -\n> -\targv_array_pushl(&cp.args,\n> -\t\t\t \"config\", \"--bool\", \"rebase.usebuiltin\", NULL);\n> -\tcp.git_cmd = 1;\n> -\tif (capture_command(&cp, &out, 6)) {\n> -\t\tstrbuf_release(&out);\n> -\t\treturn 1;\n> -\t}\n> -\n> -\tstrbuf_trim(&out);\n> -\tret = !strcmp(\"true\", out.buf);\n> -\tstrbuf_release(&out);\n> -\treturn ret;\n> -}\n> -\n>   struct rebase_options {\n>   \tenum rebase_type type;\n>   \tconst char *state_dir;\n> @@ -106,6 +83,7 @@ struct rebase_options {\n>   \tchar *strategy, *strategy_opts;\n>   \tstruct strbuf git_format_patch_opt;\n>   \tint reschedule_failed_exec;\n> +\tint use_legacy_rebase;\n>   };\n>   \n>   static int is_interactive(struct rebase_options *opts)\n> @@ -869,6 +847,11 @@ static int rebase_config(const char *var, const char *value, void *data)\n>   \t\treturn 0;\n>   \t}\n>   \n> +\tif (!strcmp(var, \"rebase.usebuiltin\")) {\n> +\t\topts->use_legacy_rebase = !git_config_bool(var, value);\n> +\t\treturn 0;\n> +\t}\n> +\n>   \treturn git_default_config(var, value, data);\n>   }\n>   \n> @@ -1143,22 +1126,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>   \t};\n>   \tint i;\n>   \n> -\t/*\n> -\t * NEEDSWORK: Once the builtin rebase has been tested enough\n> -\t * and git-legacy-rebase.sh is retired to contrib/, this preamble\n> -\t * can be removed.\n> -\t */\n> -\n> -\tif (!use_builtin_rebase()) {\n> -\t\tconst char *path = mkpath(\"%s/git-legacy-rebase\",\n> -\t\t\t\t\t  git_exec_path());\n> -\n> -\t\tif (sane_execvp(path, (char **)argv) < 0)\n> -\t\t\tdie_errno(_(\"could not exec %s\"), path);\n> -\t\telse\n> -\t\t\tBUG(\"sane_execvp() returned???\");\n> -\t}\n> -\n>   \tif (argc == 2 && !strcmp(argv[1], \"-h\"))\n>   \t\tusage_with_options(builtin_rebase_usage,\n>   \t\t\t\t   builtin_rebase_options);\n> @@ -1169,6 +1136,11 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>   \n>   \tgit_config(rebase_config, &options);\n>   \n> +\tif (options.use_legacy_rebase ||\n> +\t    !git_env_bool(\"GIT_TEST_REBASE_USE_BUILTIN\", -1))\n> +\t\twarning(_(\"the rebase.useBuiltin support has been removed!\\n\"\n> +\t\t\t  \"See its entry in 'git help config' for details.\"));\n> +\n>   \tstrbuf_reset(&buf);\n>   \tstrbuf_addf(&buf, \"%s/applying\", apply_dir());\n>   \tif(file_exists(buf.buf))\n> diff --git a/git-legacy-rebase.sh b/git-legacy-rebase.sh\n> deleted file mode 100755\n> index 5c2c4e5276..0000000000\n> --- a/git-legacy-rebase.sh\n> +++ /dev/null\n> @@ -1,770 +0,0 @@\n> -#!/bin/sh\n> -#\n> -# Copyright (c) 2005 Junio C Hamano.\n> -#\n> -\n> -SUBDIRECTORY_OK=Yes\n> -OPTIONS_KEEPDASHDASH=\n> -OPTIONS_STUCKLONG=t\n> -OPTIONS_SPEC=\"\\\n> -git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] [<upstream>] [<branch>]\n> -git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] --root [<branch>]\n> -git rebase --continue | --abort | --skip | --edit-todo\n> ---\n> - Available options are\n> -v,verbose!         display a diffstat of what changed upstream\n> -q,quiet!           be quiet. implies --no-stat\n> -autostash          automatically stash/stash pop before and after\n> -fork-point         use 'merge-base --fork-point' to refine upstream\n> -onto=!             rebase onto given branch instead of upstream\n> -r,rebase-merges?   try to rebase merges instead of skipping them\n> -p,preserve-merges! try to recreate merges instead of ignoring them\n> -s,strategy=!       use the given merge strategy\n> -X,strategy-option=! pass the argument through to the merge strategy\n> -no-ff!             cherry-pick all commits, even if unchanged\n> -f,force-rebase!    cherry-pick all commits, even if unchanged\n> -m,merge!           use merging strategies to rebase\n> -i,interactive!     let the user edit the list of commits to rebase\n> -x,exec=!           add exec lines after each commit of the editable list\n> -k,keep-empty\t   preserve empty commits during rebase\n> -allow-empty-message allow rebasing commits with empty messages\n> -stat!              display a diffstat of what changed upstream\n> -n,no-stat!         do not show diffstat of what changed upstream\n> -verify             allow pre-rebase hook to run\n> -rerere-autoupdate  allow rerere to update index with resolved conflicts\n> -root!              rebase all reachable commits up to the root(s)\n> -autosquash         move commits that begin with squash!/fixup! under -i\n> -signoff            add a Signed-off-by: line to each commit\n> -committer-date-is-author-date! passed to 'git am'\n> -ignore-date!       passed to 'git am'\n> -whitespace=!       passed to 'git apply'\n> -ignore-whitespace! passed to 'git apply'\n> -C=!                passed to 'git apply'\n> -S,gpg-sign?        GPG-sign commits\n> - Actions:\n> -continue!          continue\n> -abort!             abort and check out the original branch\n> -skip!              skip current patch and continue\n> -edit-todo!         edit the todo list during an interactive rebase\n> -quit!              abort but keep HEAD where it is\n> -show-current-patch! show the patch file being applied or merged\n> -reschedule-failed-exec automatically reschedule failed exec commands\n> -\"\n> -. git-sh-setup\n> -set_reflog_action rebase\n> -require_work_tree_exists\n> -cd_to_toplevel\n> -\n> -LF='\n> -'\n> -ok_to_skip_pre_rebase=\n> -\n> -squash_onto=\n> -unset onto\n> -unset restrict_revision\n> -cmd=\n> -strategy=\n> -strategy_opts=\n> -do_merge=\n> -merge_dir=\"$GIT_DIR\"/rebase-merge\n> -apply_dir=\"$GIT_DIR\"/rebase-apply\n> -verbose=\n> -diffstat=\n> -test \"$(git config --bool rebase.stat)\" = true && diffstat=t\n> -autostash=\"$(git config --bool rebase.autostash || echo false)\"\n> -fork_point=auto\n> -git_am_opt=\n> -git_format_patch_opt=\n> -rebase_root=\n> -force_rebase=\n> -allow_rerere_autoupdate=\n> -# Non-empty if a rebase was in progress when 'git rebase' was invoked\n> -in_progress=\n> -# One of {am, merge, interactive}\n> -type=\n> -# One of {\"$GIT_DIR\"/rebase-apply, \"$GIT_DIR\"/rebase-merge}\n> -state_dir=\n> -# One of {'', continue, skip, abort}, as parsed from command line\n> -action=\n> -rebase_merges=\n> -rebase_cousins=\n> -preserve_merges=\n> -autosquash=\n> -keep_empty=\n> -allow_empty_message=--allow-empty-message\n> -signoff=\n> -reschedule_failed_exec=\n> -test \"$(git config --bool rebase.autosquash)\" = \"true\" && autosquash=t\n> -case \"$(git config --bool commit.gpgsign)\" in\n> -true)\tgpg_sign_opt=-S ;;\n> -*)\tgpg_sign_opt= ;;\n> -esac\n> -test \"$(git config --bool rebase.reschedulefailedexec)\" = \"true\" &&\n> -reschedule_failed_exec=--reschedule-failed-exec\n> -. git-rebase--common\n> -\n> -read_basic_state () {\n> -\ttest -f \"$state_dir/head-name\" &&\n> -\ttest -f \"$state_dir/onto\" &&\n> -\thead_name=$(cat \"$state_dir\"/head-name) &&\n> -\tonto=$(cat \"$state_dir\"/onto) &&\n> -\t# We always write to orig-head, but interactive rebase used to write to\n> -\t# head. Fall back to reading from head to cover for the case that the\n> -\t# user upgraded git with an ongoing interactive rebase.\n> -\tif test -f \"$state_dir\"/orig-head\n> -\tthen\n> -\t\torig_head=$(cat \"$state_dir\"/orig-head)\n> -\telse\n> -\t\torig_head=$(cat \"$state_dir\"/head)\n> -\tfi &&\n> -\ttest -f \"$state_dir\"/quiet && GIT_QUIET=t\n> -\ttest -f \"$state_dir\"/verbose && verbose=t\n> -\ttest -f \"$state_dir\"/strategy && strategy=\"$(cat \"$state_dir\"/strategy)\"\n> -\ttest -f \"$state_dir\"/strategy_opts &&\n> -\t\tstrategy_opts=\"$(cat \"$state_dir\"/strategy_opts)\"\n> -\ttest -f \"$state_dir\"/allow_rerere_autoupdate &&\n> -\t\tallow_rerere_autoupdate=\"$(cat \"$state_dir\"/allow_rerere_autoupdate)\"\n> -\ttest -f \"$state_dir\"/gpg_sign_opt &&\n> -\t\tgpg_sign_opt=\"$(cat \"$state_dir\"/gpg_sign_opt)\"\n> -\ttest -f \"$state_dir\"/signoff && {\n> -\t\tsignoff=\"$(cat \"$state_dir\"/signoff)\"\n> -\t\tforce_rebase=t\n> -\t}\n> -\ttest -f \"$state_dir\"/reschedule-failed-exec &&\n> -\t\treschedule_failed_exec=t\n> -}\n> -\n> -finish_rebase () {\n> -\trm -f \"$(git rev-parse --git-path REBASE_HEAD)\"\n> -\tapply_autostash &&\n> -\t{ git gc --auto || true; } &&\n> -\trm -rf \"$state_dir\"\n> -}\n> -\n> -run_interactive () {\n> -\tGIT_CHERRY_PICK_HELP=\"$resolvemsg\"\n> -\texport GIT_CHERRY_PICK_HELP\n> -\n> -\ttest -n \"$keep_empty\" && keep_empty=\"--keep-empty\"\n> -\ttest -n \"$rebase_merges\" && rebase_merges=\"--rebase-merges\"\n> -\ttest -n \"$rebase_cousins\" && rebase_cousins=\"--rebase-cousins\"\n> -\ttest -n \"$autosquash\" && autosquash=\"--autosquash\"\n> -\ttest -n \"$verbose\" && verbose=\"--verbose\"\n> -\ttest -n \"$force_rebase\" && force_rebase=\"--no-ff\"\n> -\ttest -n \"$restrict_revision\" && \\\n> -\t\trestrict_revision=\"--restrict-revision=^$restrict_revision\"\n> -\ttest -n \"$upstream\" && upstream=\"--upstream=$upstream\"\n> -\ttest -n \"$onto\" && onto=\"--onto=$onto\"\n> -\ttest -n \"$squash_onto\" && squash_onto=\"--squash-onto=$squash_onto\"\n> -\ttest -n \"$onto_name\" && onto_name=\"--onto-name=$onto_name\"\n> -\ttest -n \"$head_name\" && head_name=\"--head-name=$head_name\"\n> -\ttest -n \"$strategy\" && strategy=\"--strategy=$strategy\"\n> -\ttest -n \"$strategy_opts\" && strategy_opts=\"--strategy-opts=$strategy_opts\"\n> -\ttest -n \"$switch_to\" && switch_to=\"--switch-to=$switch_to\"\n> -\ttest -n \"$cmd\" && cmd=\"--cmd=$cmd\"\n> -\ttest -n \"$action\" && action=\"--$action\"\n> -\n> -\texec git rebase--interactive \"$action\" \"$keep_empty\" \"$rebase_merges\" \"$rebase_cousins\" \\\n> -\t\t\"$upstream\" \"$onto\" \"$squash_onto\" \"$restrict_revision\" \\\n> -\t\t\"$allow_empty_message\" \"$autosquash\" \"$verbose\" \\\n> -\t\t\"$force_rebase\" \"$onto_name\" \"$head_name\" \"$strategy\" \\\n> -\t\t\"$strategy_opts\" \"$cmd\" \"$switch_to\" \\\n> -\t\t\"$allow_rerere_autoupdate\" \"$gpg_sign_opt\" \"$signoff\" \\\n> -\t\t\"$reschedule_failed_exec\"\n> -}\n> -\n> -run_specific_rebase () {\n> -\tif [ \"$interactive_rebase\" = implied ]; then\n> -\t\tGIT_SEQUENCE_EDITOR=:\n> -\t\texport GIT_SEQUENCE_EDITOR\n> -\t\tautosquash=\n> -\tfi\n> -\n> -\tif test -n \"$interactive_rebase\" -a -z \"$preserve_merges\"\n> -\tthen\n> -\t\trun_interactive\n> -\telse\n> -\t\t. git-rebase--$type\n> -\n> -\t\tif test -z \"$preserve_merges\"\n> -\t\tthen\n> -\t\t\tgit_rebase__$type\n> -\t\telse\n> -\t\t\tgit_rebase__preserve_merges\n> -\t\tfi\n> -\tfi\n> -\n> -\tret=$?\n> -\tif test $ret -eq 0\n> -\tthen\n> -\t\tfinish_rebase\n> -\telif test $ret -eq 2 # special exit status for rebase -p\n> -\tthen\n> -\t\tapply_autostash &&\n> -\t\trm -rf \"$state_dir\" &&\n> -\t\tdie \"Nothing to do\"\n> -\tfi\n> -\texit $ret\n> -}\n> -\n> -run_pre_rebase_hook () {\n> -\tif test -z \"$ok_to_skip_pre_rebase\" &&\n> -\t   test -x \"$(git rev-parse --git-path hooks/pre-rebase)\"\n> -\tthen\n> -\t\t\"$(git rev-parse --git-path hooks/pre-rebase)\" ${1+\"$@\"} ||\n> -\t\tdie \"$(gettext \"The pre-rebase hook refused to rebase.\")\"\n> -\tfi\n> -}\n> -\n> -test -f \"$apply_dir\"/applying &&\n> -\tdie \"$(gettext \"It looks like 'git am' is in progress. Cannot rebase.\")\"\n> -\n> -if test -d \"$apply_dir\"\n> -then\n> -\ttype=am\n> -\tstate_dir=\"$apply_dir\"\n> -elif test -d \"$merge_dir\"\n> -then\n> -\ttype=interactive\n> -\tif test -d \"$merge_dir\"/rewritten\n> -\tthen\n> -\t\ttype=preserve-merges\n> -\t\tinteractive_rebase=explicit\n> -\t\tpreserve_merges=t\n> -\telif test -f \"$merge_dir\"/interactive\n> -\tthen\n> -\t\tinteractive_rebase=explicit\n> -\tfi\n> -\tstate_dir=\"$merge_dir\"\n> -fi\n> -test -n \"$type\" && in_progress=t\n> -\n> -total_argc=$#\n> -while test $# != 0\n> -do\n> -\tcase \"$1\" in\n> -\t--no-verify)\n> -\t\tok_to_skip_pre_rebase=yes\n> -\t\t;;\n> -\t--verify)\n> -\t\tok_to_skip_pre_rebase=\n> -\t\t;;\n> -\t--continue|--skip|--abort|--quit|--edit-todo|--show-current-patch)\n> -\t\ttest $total_argc -eq 2 || usage\n> -\t\taction=${1##--}\n> -\t\t;;\n> -\t--onto=*)\n> -\t\tonto=\"${1#--onto=}\"\n> -\t\t;;\n> -\t--exec=*)\n> -\t\tcmd=\"${cmd}exec ${1#--exec=}${LF}\"\n> -\t\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n> -\t\t;;\n> -\t--interactive)\n> -\t\tinteractive_rebase=explicit\n> -\t\t;;\n> -\t--keep-empty)\n> -\t\tkeep_empty=yes\n> -\t\t;;\n> -\t--allow-empty-message)\n> -\t\tallow_empty_message=--allow-empty-message\n> -\t\t;;\n> -\t--no-keep-empty)\n> -\t\tkeep_empty=\n> -\t\t;;\n> -\t--rebase-merges)\n> -\t\trebase_merges=t\n> -\t\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n> -\t\t;;\n> -\t--rebase-merges=*)\n> -\t\trebase_merges=t\n> -\t\tcase \"${1#*=}\" in\n> -\t\trebase-cousins) rebase_cousins=t;;\n> -\t\tno-rebase-cousins) rebase_cousins=;;\n> -\t\t*) die \"Unknown mode: $1\";;\n> -\t\tesac\n> -\t\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n> -\t\t;;\n> -\t--preserve-merges)\n> -\t\tpreserve_merges=t\n> -\t\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n> -\t\t;;\n> -\t--autosquash)\n> -\t\tautosquash=t\n> -\t\t;;\n> -\t--no-autosquash)\n> -\t\tautosquash=\n> -\t\t;;\n> -\t--fork-point)\n> -\t\tfork_point=t\n> -\t\t;;\n> -\t--no-fork-point)\n> -\t\tfork_point=\n> -\t\t;;\n> -\t--merge)\n> -\t\tdo_merge=t\n> -\t\t;;\n> -\t--strategy-option=*)\n> -\t\tstrategy_opts=\"$strategy_opts $(git rev-parse --sq-quote \"--${1#--strategy-option=}\" | sed -e s/^.//)\"\n> -\t\tdo_merge=t\n> -\t\ttest -z \"$strategy\" && strategy=recursive\n> -\t\t;;\n> -\t--strategy=*)\n> -\t\tstrategy=\"${1#--strategy=}\"\n> -\t\tdo_merge=t\n> -\t\t;;\n> -\t--no-stat)\n> -\t\tdiffstat=\n> -\t\t;;\n> -\t--stat)\n> -\t\tdiffstat=t\n> -\t\t;;\n> -\t--autostash)\n> -\t\tautostash=true\n> -\t\t;;\n> -\t--no-autostash)\n> -\t\tautostash=false\n> -\t\t;;\n> -\t--verbose)\n> -\t\tverbose=t\n> -\t\tdiffstat=t\n> -\t\tGIT_QUIET=\n> -\t\t;;\n> -\t--quiet)\n> -\t\tGIT_QUIET=t\n> -\t\tgit_am_opt=\"$git_am_opt -q\"\n> -\t\tverbose=\n> -\t\tdiffstat=\n> -\t\t;;\n> -\t--whitespace=*)\n> -\t\tgit_am_opt=\"$git_am_opt --whitespace=${1#--whitespace=}\"\n> -\t\tcase \"${1#--whitespace=}\" in\n> -\t\tfix|strip)\n> -\t\t\tforce_rebase=t\n> -\t\t\t;;\n> -\t\twarn|nowarn|error|error-all)\n> -\t\t\t;; # okay, known whitespace option\n> -\t\t*)\n> -\t\t\tdie \"fatal: Invalid whitespace option: '${1#*=}'\"\n> -\t\t\t;;\n> -\t\tesac\n> -\t\t;;\n> -\t--ignore-whitespace)\n> -\t\tgit_am_opt=\"$git_am_opt $1\"\n> -\t\t;;\n> -\t--signoff)\n> -\t\tsignoff=--signoff\n> -\t\t;;\n> -\t--no-signoff)\n> -\t\tsignoff=\n> -\t\t;;\n> -\t--committer-date-is-author-date|--ignore-date)\n> -\t\tgit_am_opt=\"$git_am_opt $1\"\n> -\t\tforce_rebase=t\n> -\t\t;;\n> -\t-C*[!0-9]*)\n> -\t\tdie \"fatal: switch \\`C' expects a numerical value\"\n> -\t\t;;\n> -\t-C*)\n> -\t\tgit_am_opt=\"$git_am_opt $1\"\n> -\t\t;;\n> -\t--root)\n> -\t\trebase_root=t\n> -\t\t;;\n> -\t--force-rebase|--no-ff)\n> -\t\tforce_rebase=t\n> -\t\t;;\n> -\t--rerere-autoupdate|--no-rerere-autoupdate)\n> -\t\tallow_rerere_autoupdate=\"$1\"\n> -\t\t;;\n> -\t--gpg-sign)\n> -\t\tgpg_sign_opt=-S\n> -\t\t;;\n> -\t--gpg-sign=*)\n> -\t\tgpg_sign_opt=\"-S${1#--gpg-sign=}\"\n> -\t\t;;\n> -\t--reschedule-failed-exec)\n> -\t\treschedule_failed_exec=--reschedule-failed-exec\n> -\t\t;;\n> -\t--no-reschedule-failed-exec)\n> -\t\treschedule_failed_exec=\n> -\t\t;;\n> -\t--)\n> -\t\tshift\n> -\t\tbreak\n> -\t\t;;\n> -\t*)\n> -\t\tusage\n> -\t\t;;\n> -\tesac\n> -\tshift\n> -done\n> -test $# -gt 2 && usage\n> -\n> -if test -n \"$action\"\n> -then\n> -\ttest -z \"$in_progress\" && die \"$(gettext \"No rebase in progress?\")\"\n> -\t# Only interactive rebase uses detailed reflog messages\n> -\tif test -n \"$interactive_rebase\" && test \"$GIT_REFLOG_ACTION\" = rebase\n> -\tthen\n> -\t\tGIT_REFLOG_ACTION=\"rebase -i ($action)\"\n> -\t\texport GIT_REFLOG_ACTION\n> -\tfi\n> -fi\n> -\n> -if test \"$action\" = \"edit-todo\" && test -z \"$interactive_rebase\"\n> -then\n> -\tdie \"$(gettext \"The --edit-todo action can only be used during interactive rebase.\")\"\n> -fi\n> -\n> -case \"$action\" in\n> -continue)\n> -\t# Sanity check\n> -\tgit rev-parse --verify HEAD >/dev/null ||\n> -\t\tdie \"$(gettext \"Cannot read HEAD\")\"\n> -\tgit update-index --ignore-submodules --refresh &&\n> -\tgit diff-files --quiet --ignore-submodules || {\n> -\t\techo \"$(gettext \"You must edit all merge conflicts and then\n> -mark them as resolved using git add\")\"\n> -\t\texit 1\n> -\t}\n> -\tread_basic_state\n> -\trun_specific_rebase\n> -\t;;\n> -skip)\n> -\toutput git reset --hard HEAD || exit $?\n> -\tread_basic_state\n> -\trun_specific_rebase\n> -\t;;\n> -abort)\n> -\tgit rerere clear\n> -\tread_basic_state\n> -\tcase \"$head_name\" in\n> -\trefs/*)\n> -\t\tgit symbolic-ref -m \"rebase: aborting\" HEAD $head_name ||\n> -\t\tdie \"$(eval_gettext \"Could not move back to \\$head_name\")\"\n> -\t\t;;\n> -\tesac\n> -\toutput git reset --hard $orig_head\n> -\tfinish_rebase\n> -\texit\n> -\t;;\n> -quit)\n> -\texec rm -rf \"$state_dir\"\n> -\t;;\n> -edit-todo)\n> -\trun_specific_rebase\n> -\t;;\n> -show-current-patch)\n> -\trun_specific_rebase\n> -\tdie \"BUG: run_specific_rebase is not supposed to return here\"\n> -\t;;\n> -esac\n> -\n> -# Make sure no rebase is in progress\n> -if test -n \"$in_progress\"\n> -then\n> -\tstate_dir_base=${state_dir##*/}\n> -\tcmd_live_rebase=\"git rebase (--continue | --abort | --skip)\"\n> -\tcmd_clear_stale_rebase=\"rm -fr \\\"$state_dir\\\"\"\n> -\tdie \"\n> -$(eval_gettext 'It seems that there is already a $state_dir_base directory, and\n> -I wonder if you are in the middle of another rebase.  If that is the\n> -case, please try\n> -\t$cmd_live_rebase\n> -If that is not the case, please\n> -\t$cmd_clear_stale_rebase\n> -and run me again.  I am stopping in case you still have something\n> -valuable there.')\"\n> -fi\n> -\n> -if test -n \"$rebase_root\" && test -z \"$onto\"\n> -then\n> -\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n> -fi\n> -\n> -if test -n \"$keep_empty\"\n> -then\n> -\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n> -fi\n> -\n> -actually_interactive=\n> -if test -n \"$interactive_rebase\"\n> -then\n> -\tif test -z \"$preserve_merges\"\n> -\tthen\n> -\t\ttype=interactive\n> -\telse\n> -\t\ttype=preserve-merges\n> -\tfi\n> -\tactually_interactive=t\n> -\tstate_dir=\"$merge_dir\"\n> -elif test -n \"$do_merge\"\n> -then\n> -\tinteractive_rebase=implied\n> -\ttype=interactive\n> -\tstate_dir=\"$merge_dir\"\n> -else\n> -\ttype=am\n> -\tstate_dir=\"$apply_dir\"\n> -fi\n> -\n> -if test -t 2 && test -z \"$GIT_QUIET\"\n> -then\n> -\tgit_format_patch_opt=\"$git_format_patch_opt --progress\"\n> -fi\n> -\n> -incompatible_opts=$(echo \" $git_am_opt \" | \\\n> -\t\t    sed -e 's/ -q / /g' -e 's/^ \\(.*\\) $/\\1/')\n> -if test -n \"$incompatible_opts\"\n> -then\n> -\tif test -n \"$actually_interactive\" || test \"$do_merge\"\n> -\tthen\n> -\t\tdie \"$(gettext \"fatal: cannot combine am options with either interactive or merge options\")\"\n> -\tfi\n> -fi\n> -\n> -if test -n \"$signoff\"\n> -then\n> -\ttest -n \"$preserve_merges\" &&\n> -\t\tdie \"$(gettext \"fatal: cannot combine '--signoff' with '--preserve-merges'\")\"\n> -\tgit_am_opt=\"$git_am_opt $signoff\"\n> -\tforce_rebase=t\n> -fi\n> -\n> -if test -n \"$preserve_merges\"\n> -then\n> -\t# Note: incompatibility with --signoff handled in signoff block above\n> -\t# Note: incompatibility with --interactive is just a strong warning;\n> -\t#       git-rebase.txt caveats with \"unless you know what you are doing\"\n> -\ttest -n \"$rebase_merges\" &&\n> -\t\tdie \"$(gettext \"fatal: cannot combine '--preserve-merges' with '--rebase-merges'\")\"\n> -\n> -\ttest -n \"$reschedule_failed_exec\" &&\n> -\t\tdie \"$(gettext \"error: cannot combine '--preserve-merges' with '--reschedule-failed-exec'\")\"\n> -fi\n> -\n> -if test -n \"$rebase_merges\"\n> -then\n> -\ttest -n \"$strategy_opts\" &&\n> -\t\tdie \"$(gettext \"fatal: cannot combine '--rebase-merges' with '--strategy-option'\")\"\n> -\ttest -n \"$strategy\" &&\n> -\t\tdie \"$(gettext \"fatal: cannot combine '--rebase-merges' with '--strategy'\")\"\n> -fi\n> -\n> -if test -z \"$rebase_root\"\n> -then\n> -\tcase \"$#\" in\n> -\t0)\n> -\t\tif ! upstream_name=$(git rev-parse --symbolic-full-name \\\n> -\t\t\t--verify -q @{upstream} 2>/dev/null)\n> -\t\tthen\n> -\t\t\t. git-parse-remote\n> -\t\t\terror_on_missing_default_upstream \"rebase\" \"rebase\" \\\n> -\t\t\t\t\"against\" \"git rebase $(gettext '<branch>')\"\n> -\t\tfi\n> -\n> -\t\ttest \"$fork_point\" = auto && fork_point=t\n> -\t\t;;\n> -\t*)\tupstream_name=\"$1\"\n> -\t\tif test \"$upstream_name\" = \"-\"\n> -\t\tthen\n> -\t\t\tupstream_name=\"@{-1}\"\n> -\t\tfi\n> -\t\tshift\n> -\t\t;;\n> -\tesac\n> -\tupstream=$(peel_committish \"${upstream_name}\") ||\n> -\tdie \"$(eval_gettext \"invalid upstream '\\$upstream_name'\")\"\n> -\tupstream_arg=\"$upstream_name\"\n> -else\n> -\tif test -z \"$onto\"\n> -\tthen\n> -\t\tempty_tree=$(git hash-object -t tree /dev/null)\n> -\t\tonto=$(git commit-tree $empty_tree </dev/null)\n> -\t\tsquash_onto=\"$onto\"\n> -\tfi\n> -\tunset upstream_name\n> -\tunset upstream\n> -\ttest $# -gt 1 && usage\n> -\tupstream_arg=--root\n> -fi\n> -\n> -# Make sure the branch to rebase onto is valid.\n> -onto_name=${onto-\"$upstream_name\"}\n> -case \"$onto_name\" in\n> -*...*)\n> -\tif\tleft=${onto_name%...*} right=${onto_name#*...} &&\n> -\t\tonto=$(git merge-base --all ${left:-HEAD} ${right:-HEAD})\n> -\tthen\n> -\t\tcase \"$onto\" in\n> -\t\t?*\"$LF\"?*)\n> -\t\t\tdie \"$(eval_gettext \"\\$onto_name: there are more than one merge bases\")\"\n> -\t\t\t;;\n> -\t\t'')\n> -\t\t\tdie \"$(eval_gettext \"\\$onto_name: there is no merge base\")\"\n> -\t\t\t;;\n> -\t\tesac\n> -\telse\n> -\t\tdie \"$(eval_gettext \"\\$onto_name: there is no merge base\")\"\n> -\tfi\n> -\t;;\n> -*)\n> -\tonto=$(peel_committish \"$onto_name\") ||\n> -\tdie \"$(eval_gettext \"Does not point to a valid commit: \\$onto_name\")\"\n> -\t;;\n> -esac\n> -\n> -# If the branch to rebase is given, that is the branch we will rebase\n> -# $branch_name -- branch/commit being rebased, or HEAD (already detached)\n> -# $orig_head -- commit object name of tip of the branch before rebasing\n> -# $head_name -- refs/heads/<that-branch> or \"detached HEAD\"\n> -switch_to=\n> -case \"$#\" in\n> -1)\n> -\t# Is it \"rebase other $branchname\" or \"rebase other $commit\"?\n> -\tbranch_name=\"$1\"\n> -\tswitch_to=\"$1\"\n> -\n> -\t# Is it a local branch?\n> -\tif git show-ref --verify --quiet -- \"refs/heads/$branch_name\" &&\n> -\t   orig_head=$(git rev-parse -q --verify \"refs/heads/$branch_name\")\n> -\tthen\n> -\t\thead_name=\"refs/heads/$branch_name\"\n> -\t# If not is it a valid ref (branch or commit)?\n> -\telif orig_head=$(git rev-parse -q --verify \"$branch_name\")\n> -\tthen\n> -\t\thead_name=\"detached HEAD\"\n> -\n> -\telse\n> -\t\tdie \"$(eval_gettext \"fatal: no such branch/commit '\\$branch_name'\")\"\n> -\tfi\n> -\t;;\n> -0)\n> -\t# Do not need to switch branches, we are already on it.\n> -\tif branch_name=$(git symbolic-ref -q HEAD)\n> -\tthen\n> -\t\thead_name=$branch_name\n> -\t\tbranch_name=$(expr \"z$branch_name\" : 'zrefs/heads/\\(.*\\)')\n> -\telse\n> -\t\thead_name=\"detached HEAD\"\n> -\t\tbranch_name=HEAD\n> -\tfi\n> -\torig_head=$(git rev-parse --verify HEAD) || exit\n> -\t;;\n> -*)\n> -\tdie \"BUG: unexpected number of arguments left to parse\"\n> -\t;;\n> -esac\n> -\n> -if test \"$fork_point\" = t\n> -then\n> -\tnew_upstream=$(git merge-base --fork-point \"$upstream_name\" \\\n> -\t\t\t\"${switch_to:-HEAD}\")\n> -\tif test -n \"$new_upstream\"\n> -\tthen\n> -\t\trestrict_revision=$new_upstream\n> -\tfi\n> -fi\n> -\n> -if test \"$autostash\" = true && ! (require_clean_work_tree) 2>/dev/null\n> -then\n> -\tstash_sha1=$(git stash create \"autostash\") ||\n> -\tdie \"$(gettext 'Cannot autostash')\"\n> -\n> -\tmkdir -p \"$state_dir\" &&\n> -\techo $stash_sha1 >\"$state_dir/autostash\" &&\n> -\tstash_abbrev=$(git rev-parse --short $stash_sha1) &&\n> -\techo \"$(eval_gettext 'Created autostash: $stash_abbrev')\" &&\n> -\tgit reset --hard\n> -fi\n> -\n> -require_clean_work_tree \"rebase\" \"$(gettext \"Please commit or stash them.\")\"\n> -\n> -# Now we are rebasing commits $upstream..$orig_head (or with --root,\n> -# everything leading up to $orig_head) on top of $onto\n> -\n> -# Check if we are already based on $onto with linear history,\n> -# but this should be done only when upstream and onto are the same\n> -# and if this is not an interactive rebase.\n> -mb=$(git merge-base \"$onto\" \"$orig_head\")\n> -if test -z \"$actually_interactive\" && test \"$upstream\" = \"$onto\" &&\n> -\ttest \"$mb\" = \"$onto\" && test -z \"$restrict_revision\" &&\n> -\t# linear history?\n> -\t! (git rev-list --parents \"$onto\"..\"$orig_head\" | sane_grep \" .* \") > /dev/null\n> -then\n> -\tif test -z \"$force_rebase\"\n> -\tthen\n> -\t\t# Lazily switch to the target branch if needed...\n> -\t\ttest -z \"$switch_to\" ||\n> -\t\tGIT_REFLOG_ACTION=\"$GIT_REFLOG_ACTION: checkout $switch_to\" \\\n> -\t\t\tgit checkout -q \"$switch_to\" --\n> -\t\tif test \"$branch_name\" = \"HEAD\" &&\n> -\t\t\t ! git symbolic-ref -q HEAD\n> -\t\tthen\n> -\t\t\tsay \"$(eval_gettext \"HEAD is up to date.\")\"\n> -\t\telse\n> -\t\t\tsay \"$(eval_gettext \"Current branch \\$branch_name is up to date.\")\"\n> -\t\tfi\n> -\t\tfinish_rebase\n> -\t\texit 0\n> -\telse\n> -\t\tif test \"$branch_name\" = \"HEAD\" &&\n> -\t\t\t ! git symbolic-ref -q HEAD\n> -\t\tthen\n> -\t\t\tsay \"$(eval_gettext \"HEAD is up to date, rebase forced.\")\"\n> -\t\telse\n> -\t\t\tsay \"$(eval_gettext \"Current branch \\$branch_name is up to date, rebase forced.\")\"\n> -\t\tfi\n> -\tfi\n> -fi\n> -\n> -# If a hook exists, give it a chance to interrupt\n> -run_pre_rebase_hook \"$upstream_arg\" \"$@\"\n> -\n> -if test -n \"$diffstat\"\n> -then\n> -\tif test -n \"$verbose\"\n> -\tthen\n> -\t\tif test -z \"$mb\"\n> -\t\tthen\n> -\t\t\techo \"$(eval_gettext \"Changes to \\$onto:\")\"\n> -\t\telse\n> -\t\t\techo \"$(eval_gettext \"Changes from \\$mb to \\$onto:\")\"\n> -\t\tfi\n> -\tfi\n> -\tmb_tree=\"${mb:-$(git hash-object -t tree /dev/null)}\"\n> -\t# We want color (if set), but no pager\n> -\tGIT_PAGER='' git diff --stat --summary \"$mb_tree\" \"$onto\"\n> -fi\n> -\n> -if test -z \"$actually_interactive\" && test \"$mb\" = \"$orig_head\"\n> -then\n> -\tsay \"$(eval_gettext \"Fast-forwarded \\$branch_name to \\$onto_name.\")\"\n> -\tGIT_REFLOG_ACTION=\"$GIT_REFLOG_ACTION: checkout $onto_name\" \\\n> -\t\tgit checkout -q \"$onto^0\" || die \"could not detach HEAD\"\n> -\t# If the $onto is a proper descendant of the tip of the branch, then\n> -\t# we just fast-forwarded.\n> -\tgit update-ref ORIG_HEAD $orig_head\n> -\tmove_to_original_branch\n> -\tfinish_rebase\n> -\texit 0\n> -fi\n> -\n> -test -n \"$interactive_rebase\" && run_specific_rebase\n> -\n> -# Detach HEAD and reset the tree\n> -say \"$(gettext \"First, rewinding head to replay your work on top of it...\")\"\n> -\n> -GIT_REFLOG_ACTION=\"$GIT_REFLOG_ACTION: checkout $onto_name\" \\\n> -\tgit checkout -q \"$onto^0\" || die \"could not detach HEAD\"\n> -git update-ref ORIG_HEAD $orig_head\n> -\n> -if test -n \"$rebase_root\"\n> -then\n> -\trevisions=\"$onto..$orig_head\"\n> -else\n> -\trevisions=\"${restrict_revision-$upstream}..$orig_head\"\n> -fi\n> -\n> -run_specific_rebase\n> diff --git a/t/README b/t/README\n> index 7a3d582267..385262357b 100644\n> --- a/t/README\n> +++ b/t/README\n> @@ -379,10 +379,6 @@ the --no-sparse command-line argument.\n>   GIT_TEST_PRELOAD_INDEX=<boolean> exercises the preload-index code path\n>   by overriding the minimum number of cache entries required per thread.\n>   \n> -GIT_TEST_REBASE_USE_BUILTIN=<boolean>, when false, disables the\n> -builtin version of git-rebase. See 'rebase.useBuiltin' in\n> -git-config(1).\n> -\n>   GIT_TEST_INDEX_THREADS=<n> enables exercising the multi-threaded loading\n>   of the index for the whole test suite by bypassing the default number of\n>   cache entries and thread minimums. Setting this to 1 will make the\n> diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh\n> index 3e73f7584c..a809de9304 100755\n> --- a/t/t3400-rebase.sh\n> +++ b/t/t3400-rebase.sh\n> @@ -311,4 +311,20 @@ test_expect_success 'rebase--merge.sh and --show-current-patch' '\n>   \t)\n>   '\n>   \n> +test_expect_success 'rebase -c rebase.useBuiltin=false warning' '\n> +\texpected=\"rebase.useBuiltin support has been removed\" &&\n> +\n> +\t# Only warn when the legacy rebase is requested...\n> +\ttest_must_fail git -c rebase.useBuiltin=false rebase 2>err &&\n> +\ttest_i18ngrep \"$expected\" err &&\n> +\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=false git rebase 2>err &&\n> +\ttest_i18ngrep \"$expected\" err &&\n> +\n> +\t# ...not when we would have used the built-in anyway\n> +\ttest_must_fail git -c rebase.useBuiltin=true rebase 2>err &&\n> +\ttest_must_be_empty err &&\n> +\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=true git rebase 2>err &&\n> +\ttest_must_be_empty err\n> +'\n> +\n>   test_done\n> diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\n> index b60b11f9f2..1723e1a858 100755\n> --- a/t/t3404-rebase-interactive.sh\n> +++ b/t/t3404-rebase-interactive.sh\n> @@ -149,12 +149,10 @@ test_expect_success 'rebase -i with the exec command checks tree cleanness' '\n>   \n>   test_expect_success 'rebase -x with empty command fails' '\n>   \ttest_when_finished \"git rebase --abort ||:\" &&\n> -\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=true \\\n> -\t\tgit rebase -x \"\" @ 2>actual &&\n> +\ttest_must_fail env git rebase -x \"\" @ 2>actual &&\n>   \ttest_write_lines \"error: empty exec command\" >expected &&\n>   \ttest_i18ncmp expected actual &&\n> -\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=true \\\n> -\t\tgit rebase -x \" \" @ 2>actual &&\n> +\ttest_must_fail env git rebase -x \" \" @ 2>actual &&\n>   \ttest_i18ncmp expected actual\n>   '\n>   \n> @@ -162,8 +160,7 @@ LF='\n>   '\n>   test_expect_success 'rebase -x with newline in command fails' '\n>   \ttest_when_finished \"git rebase --abort ||:\" &&\n> -\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=true \\\n> -\t\tgit rebase -x \"a${LF}b\" @ 2>actual &&\n> +\ttest_must_fail env git rebase -x \"a${LF}b\" @ 2>actual &&\n>   \ttest_write_lines \"error: exec commands cannot contain newlines\" \\\n>   \t\t\t >expected &&\n>   \ttest_i18ncmp expected actual\n> \n"},{"id":"371802","messageId":"20190318110152.27246-1-avarab@gmail.com","threadId":"50341","inReplyTo":"8b912120-d9c9-be6c-d7ac-dd4036d3100f@gmail.com","subject":"[PATCH v4] rebase: remove the rebase.useBuiltin setting","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2019-03-18T11:01:52Z","receivedAt":"2019-03-18T11:02:09Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Remove the rebase.useBuiltin setting, which was added as an escape\nhatch to disable the builtin version of rebase first released with Git\n2.20.\n\nSee [1] for the initial implementation of rebase.useBuiltin, and [2]\nand [3] for the documentation and corresponding\nGIT_TEST_REBASE_USE_BUILTIN option.\n\nCarrying the legacy version is a maintenance burden as seen in\n7e097e27d3 (\"legacy-rebase: backport -C<n> and --whitespace=<option>\nchecks\", 2018-11-20) and 9aea5e9286 (\"rebase: fix regression in\nrebase.useBuiltin=false test mode\", 2019-02-13). Since the built-in\nversion has been shown to be stable enough let's remove the legacy\nversion.\n\nAs noted in [3] having use_builtin_rebase() shell out to get its\nconfig doesn't make any sense anymore, that was done for the purposes\nof spawning the legacy rebase without having modified any global\nstate. Let's instead handle this case in rebase_config().\n\nThere's still a bunch of references to git-legacy-rebase in po/*.po,\nbut those will be dealt with in time by the i18n effort.\n\nEven though this configuration variable only existed two releases\nlet's not entirely delete the entry from the docs, but note its\nabsence. Individual versions of git tend to be around for a while due\nto distro packaging timelines, so e.g. if we're \"lucky\" a given\nversion like 2.21 might be installed on say OSX for half a decade.\n\nThat'll mean some people probably setting this in config, and then\nwhen they later wonder if it's needed they can Google search the\nconfig option name or check it in git-config. It also allows us to\nrefer to the docs from the warning for details.\n\n1. 55071ea248 (\"rebase: start implementing it as a builtin\",\n   2018-08-07)\n2. d8d0a546f0 (\"rebase doc: document rebase.useBuiltin\", 2018-11-14)\n3. 62c23938fa (\"tests: add a special setup where rebase.useBuiltin is\n   off\", 2018-11-14)\n3. https://public-inbox.org/git/nycvar.QRO.7.76.6.1903141544110.41@tvgsbejvaqbjf.bet/\n\nAcked-by: Johannes Schindelin <johannes.schindelin@gmx.de>\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n\nFix wording issues pointed out by Phillip & incorporated the Acked-by\nin Junio's push-out & added my SOB.\n\nThe confusion with \"one release\" was a) I'd initially written this\nbefore 2.21 was cut and forgot to change that 2) I was then using\n\"between\" in the inclusive sense \"pick a number between 1 and\n10\". Phillip's suggestion is better.\n\nRange-diff:\n1:  799dd15e4fd ! 1:  9ca747cb1f5 rebase: remove the rebase.useBuiltin setting\n    @@ -25,7 +25,7 @@\n         There's still a bunch of references to git-legacy-rebase in po/*.po,\n         but those will be dealt with in time by the i18n effort.\n     \n    -    Even though this configuration variable only existed for one release\n    +    Even though this configuration variable only existed two releases\n         let's not entirely delete the entry from the docs, but note its\n         absence. Individual versions of git tend to be around for a while due\n         to distro packaging timelines, so e.g. if we're \"lucky\" a given\n    @@ -43,6 +43,9 @@\n            off\", 2018-11-14)\n         3. https://public-inbox.org/git/nycvar.QRO.7.76.6.1903141544110.41@tvgsbejvaqbjf.bet/\n     \n    +    Acked-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n    +    Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n    +\n      diff --git a/.gitignore b/.gitignore\n      --- a/.gitignore\n      +++ b/.gitignore\n    @@ -72,8 +75,8 @@\n     -If you find some reason to set this option to `false` other than\n     -one-off testing you should report the behavior difference as a bug in\n     -git.\n    -+\tUnused configuration variable. Used between Git version 2.20\n    -+\tand 2.21 as an escape hatch to enable the legacy shellscript\n    ++\tUnused configuration variable. Used in Git versions 2.20 and\n    ++\t2.21 as an escape hatch to enable the legacy shellscript\n     +\timplementation of rebase. Now the built-in rewrite of it in C\n     +\tis always used. Setting this will emit a warning, to alert any\n     +\tremaining users that setting this now does nothing.\n\n .gitignore                      |   1 -\n Documentation/config/rebase.txt |  17 +-\n Makefile                        |   1 -\n builtin/rebase.c                |  50 +--\n git-legacy-rebase.sh            | 770 --------------------------------\n t/README                        |   4 -\n t/t3400-rebase.sh               |  16 +\n t/t3404-rebase-interactive.sh   |   9 +-\n 8 files changed, 35 insertions(+), 833 deletions(-)\n delete mode 100755 git-legacy-rebase.sh\n\ndiff --git a/.gitignore b/.gitignore\nindex 7374587f9df..5cb84f1d1a9 100644\n--- a/.gitignore\n+++ b/.gitignore\n@@ -82,7 +82,6 @@\n /git-init-db\n /git-interpret-trailers\n /git-instaweb\n-/git-legacy-rebase\n /git-log\n /git-ls-files\n /git-ls-remote\ndiff --git a/Documentation/config/rebase.txt b/Documentation/config/rebase.txt\nindex 331d250e046..d98e32d812e 100644\n--- a/Documentation/config/rebase.txt\n+++ b/Documentation/config/rebase.txt\n@@ -1,16 +1,9 @@\n rebase.useBuiltin::\n-\tSet to `false` to use the legacy shellscript implementation of\n-\tlinkgit:git-rebase[1]. Is `true` by default, which means use\n-\tthe built-in rewrite of it in C.\n-+\n-The C rewrite is first included with Git version 2.20. This option\n-serves an an escape hatch to re-enable the legacy version in case any\n-bugs are found in the rewrite. This option and the shellscript version\n-of linkgit:git-rebase[1] will be removed in some future release.\n-+\n-If you find some reason to set this option to `false` other than\n-one-off testing you should report the behavior difference as a bug in\n-git.\n+\tUnused configuration variable. Used in Git versions 2.20 and\n+\t2.21 as an escape hatch to enable the legacy shellscript\n+\timplementation of rebase. Now the built-in rewrite of it in C\n+\tis always used. Setting this will emit a warning, to alert any\n+\tremaining users that setting this now does nothing.\n \n rebase.stat::\n \tWhether to show a diffstat of what changed upstream since the last\ndiff --git a/Makefile b/Makefile\nindex 537493822b1..9f1159cffcb 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -632,7 +632,6 @@ SCRIPT_SH += git-merge-one-file.sh\n SCRIPT_SH += git-merge-resolve.sh\n SCRIPT_SH += git-mergetool.sh\n SCRIPT_SH += git-quiltimport.sh\n-SCRIPT_SH += git-legacy-rebase.sh\n SCRIPT_SH += git-remote-testgit.sh\n SCRIPT_SH += git-request-pull.sh\n SCRIPT_SH += git-stash.sh\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 52114cbf0d9..bc3dc629c16 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -46,29 +46,6 @@ enum rebase_type {\n \tREBASE_PRESERVE_MERGES\n };\n \n-static int use_builtin_rebase(void)\n-{\n-\tstruct child_process cp = CHILD_PROCESS_INIT;\n-\tstruct strbuf out = STRBUF_INIT;\n-\tint ret, env = git_env_bool(\"GIT_TEST_REBASE_USE_BUILTIN\", -1);\n-\n-\tif (env != -1)\n-\t\treturn env;\n-\n-\targv_array_pushl(&cp.args,\n-\t\t\t \"config\", \"--bool\", \"rebase.usebuiltin\", NULL);\n-\tcp.git_cmd = 1;\n-\tif (capture_command(&cp, &out, 6)) {\n-\t\tstrbuf_release(&out);\n-\t\treturn 1;\n-\t}\n-\n-\tstrbuf_trim(&out);\n-\tret = !strcmp(\"true\", out.buf);\n-\tstrbuf_release(&out);\n-\treturn ret;\n-}\n-\n struct rebase_options {\n \tenum rebase_type type;\n \tconst char *state_dir;\n@@ -106,6 +83,7 @@ struct rebase_options {\n \tchar *strategy, *strategy_opts;\n \tstruct strbuf git_format_patch_opt;\n \tint reschedule_failed_exec;\n+\tint use_legacy_rebase;\n };\n \n static int is_interactive(struct rebase_options *opts)\n@@ -869,6 +847,11 @@ static int rebase_config(const char *var, const char *value, void *data)\n \t\treturn 0;\n \t}\n \n+\tif (!strcmp(var, \"rebase.usebuiltin\")) {\n+\t\topts->use_legacy_rebase = !git_config_bool(var, value);\n+\t\treturn 0;\n+\t}\n+\n \treturn git_default_config(var, value, data);\n }\n \n@@ -1143,22 +1126,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t};\n \tint i;\n \n-\t/*\n-\t * NEEDSWORK: Once the builtin rebase has been tested enough\n-\t * and git-legacy-rebase.sh is retired to contrib/, this preamble\n-\t * can be removed.\n-\t */\n-\n-\tif (!use_builtin_rebase()) {\n-\t\tconst char *path = mkpath(\"%s/git-legacy-rebase\",\n-\t\t\t\t\t  git_exec_path());\n-\n-\t\tif (sane_execvp(path, (char **)argv) < 0)\n-\t\t\tdie_errno(_(\"could not exec %s\"), path);\n-\t\telse\n-\t\t\tBUG(\"sane_execvp() returned???\");\n-\t}\n-\n \tif (argc == 2 && !strcmp(argv[1], \"-h\"))\n \t\tusage_with_options(builtin_rebase_usage,\n \t\t\t\t   builtin_rebase_options);\n@@ -1169,6 +1136,11 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \n \tgit_config(rebase_config, &options);\n \n+\tif (options.use_legacy_rebase ||\n+\t    !git_env_bool(\"GIT_TEST_REBASE_USE_BUILTIN\", -1))\n+\t\twarning(_(\"the rebase.useBuiltin support has been removed!\\n\"\n+\t\t\t  \"See its entry in 'git help config' for details.\"));\n+\n \tstrbuf_reset(&buf);\n \tstrbuf_addf(&buf, \"%s/applying\", apply_dir());\n \tif(file_exists(buf.buf))\ndiff --git a/git-legacy-rebase.sh b/git-legacy-rebase.sh\ndeleted file mode 100755\nindex 5c2c4e5276d..00000000000\n--- a/git-legacy-rebase.sh\n+++ /dev/null\n@@ -1,770 +0,0 @@\n-#!/bin/sh\n-#\n-# Copyright (c) 2005 Junio C Hamano.\n-#\n-\n-SUBDIRECTORY_OK=Yes\n-OPTIONS_KEEPDASHDASH=\n-OPTIONS_STUCKLONG=t\n-OPTIONS_SPEC=\"\\\n-git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] [<upstream>] [<branch>]\n-git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] --root [<branch>]\n-git rebase --continue | --abort | --skip | --edit-todo\n---\n- Available options are\n-v,verbose!         display a diffstat of what changed upstream\n-q,quiet!           be quiet. implies --no-stat\n-autostash          automatically stash/stash pop before and after\n-fork-point         use 'merge-base --fork-point' to refine upstream\n-onto=!             rebase onto given branch instead of upstream\n-r,rebase-merges?   try to rebase merges instead of skipping them\n-p,preserve-merges! try to recreate merges instead of ignoring them\n-s,strategy=!       use the given merge strategy\n-X,strategy-option=! pass the argument through to the merge strategy\n-no-ff!             cherry-pick all commits, even if unchanged\n-f,force-rebase!    cherry-pick all commits, even if unchanged\n-m,merge!           use merging strategies to rebase\n-i,interactive!     let the user edit the list of commits to rebase\n-x,exec=!           add exec lines after each commit of the editable list\n-k,keep-empty\t   preserve empty commits during rebase\n-allow-empty-message allow rebasing commits with empty messages\n-stat!              display a diffstat of what changed upstream\n-n,no-stat!         do not show diffstat of what changed upstream\n-verify             allow pre-rebase hook to run\n-rerere-autoupdate  allow rerere to update index with resolved conflicts\n-root!              rebase all reachable commits up to the root(s)\n-autosquash         move commits that begin with squash!/fixup! under -i\n-signoff            add a Signed-off-by: line to each commit\n-committer-date-is-author-date! passed to 'git am'\n-ignore-date!       passed to 'git am'\n-whitespace=!       passed to 'git apply'\n-ignore-whitespace! passed to 'git apply'\n-C=!                passed to 'git apply'\n-S,gpg-sign?        GPG-sign commits\n- Actions:\n-continue!          continue\n-abort!             abort and check out the original branch\n-skip!              skip current patch and continue\n-edit-todo!         edit the todo list during an interactive rebase\n-quit!              abort but keep HEAD where it is\n-show-current-patch! show the patch file being applied or merged\n-reschedule-failed-exec automatically reschedule failed exec commands\n-\"\n-. git-sh-setup\n-set_reflog_action rebase\n-require_work_tree_exists\n-cd_to_toplevel\n-\n-LF='\n-'\n-ok_to_skip_pre_rebase=\n-\n-squash_onto=\n-unset onto\n-unset restrict_revision\n-cmd=\n-strategy=\n-strategy_opts=\n-do_merge=\n-merge_dir=\"$GIT_DIR\"/rebase-merge\n-apply_dir=\"$GIT_DIR\"/rebase-apply\n-verbose=\n-diffstat=\n-test \"$(git config --bool rebase.stat)\" = true && diffstat=t\n-autostash=\"$(git config --bool rebase.autostash || echo false)\"\n-fork_point=auto\n-git_am_opt=\n-git_format_patch_opt=\n-rebase_root=\n-force_rebase=\n-allow_rerere_autoupdate=\n-# Non-empty if a rebase was in progress when 'git rebase' was invoked\n-in_progress=\n-# One of {am, merge, interactive}\n-type=\n-# One of {\"$GIT_DIR\"/rebase-apply, \"$GIT_DIR\"/rebase-merge}\n-state_dir=\n-# One of {'', continue, skip, abort}, as parsed from command line\n-action=\n-rebase_merges=\n-rebase_cousins=\n-preserve_merges=\n-autosquash=\n-keep_empty=\n-allow_empty_message=--allow-empty-message\n-signoff=\n-reschedule_failed_exec=\n-test \"$(git config --bool rebase.autosquash)\" = \"true\" && autosquash=t\n-case \"$(git config --bool commit.gpgsign)\" in\n-true)\tgpg_sign_opt=-S ;;\n-*)\tgpg_sign_opt= ;;\n-esac\n-test \"$(git config --bool rebase.reschedulefailedexec)\" = \"true\" &&\n-reschedule_failed_exec=--reschedule-failed-exec\n-. git-rebase--common\n-\n-read_basic_state () {\n-\ttest -f \"$state_dir/head-name\" &&\n-\ttest -f \"$state_dir/onto\" &&\n-\thead_name=$(cat \"$state_dir\"/head-name) &&\n-\tonto=$(cat \"$state_dir\"/onto) &&\n-\t# We always write to orig-head, but interactive rebase used to write to\n-\t# head. Fall back to reading from head to cover for the case that the\n-\t# user upgraded git with an ongoing interactive rebase.\n-\tif test -f \"$state_dir\"/orig-head\n-\tthen\n-\t\torig_head=$(cat \"$state_dir\"/orig-head)\n-\telse\n-\t\torig_head=$(cat \"$state_dir\"/head)\n-\tfi &&\n-\ttest -f \"$state_dir\"/quiet && GIT_QUIET=t\n-\ttest -f \"$state_dir\"/verbose && verbose=t\n-\ttest -f \"$state_dir\"/strategy && strategy=\"$(cat \"$state_dir\"/strategy)\"\n-\ttest -f \"$state_dir\"/strategy_opts &&\n-\t\tstrategy_opts=\"$(cat \"$state_dir\"/strategy_opts)\"\n-\ttest -f \"$state_dir\"/allow_rerere_autoupdate &&\n-\t\tallow_rerere_autoupdate=\"$(cat \"$state_dir\"/allow_rerere_autoupdate)\"\n-\ttest -f \"$state_dir\"/gpg_sign_opt &&\n-\t\tgpg_sign_opt=\"$(cat \"$state_dir\"/gpg_sign_opt)\"\n-\ttest -f \"$state_dir\"/signoff && {\n-\t\tsignoff=\"$(cat \"$state_dir\"/signoff)\"\n-\t\tforce_rebase=t\n-\t}\n-\ttest -f \"$state_dir\"/reschedule-failed-exec &&\n-\t\treschedule_failed_exec=t\n-}\n-\n-finish_rebase () {\n-\trm -f \"$(git rev-parse --git-path REBASE_HEAD)\"\n-\tapply_autostash &&\n-\t{ git gc --auto || true; } &&\n-\trm -rf \"$state_dir\"\n-}\n-\n-run_interactive () {\n-\tGIT_CHERRY_PICK_HELP=\"$resolvemsg\"\n-\texport GIT_CHERRY_PICK_HELP\n-\n-\ttest -n \"$keep_empty\" && keep_empty=\"--keep-empty\"\n-\ttest -n \"$rebase_merges\" && rebase_merges=\"--rebase-merges\"\n-\ttest -n \"$rebase_cousins\" && rebase_cousins=\"--rebase-cousins\"\n-\ttest -n \"$autosquash\" && autosquash=\"--autosquash\"\n-\ttest -n \"$verbose\" && verbose=\"--verbose\"\n-\ttest -n \"$force_rebase\" && force_rebase=\"--no-ff\"\n-\ttest -n \"$restrict_revision\" && \\\n-\t\trestrict_revision=\"--restrict-revision=^$restrict_revision\"\n-\ttest -n \"$upstream\" && upstream=\"--upstream=$upstream\"\n-\ttest -n \"$onto\" && onto=\"--onto=$onto\"\n-\ttest -n \"$squash_onto\" && squash_onto=\"--squash-onto=$squash_onto\"\n-\ttest -n \"$onto_name\" && onto_name=\"--onto-name=$onto_name\"\n-\ttest -n \"$head_name\" && head_name=\"--head-name=$head_name\"\n-\ttest -n \"$strategy\" && strategy=\"--strategy=$strategy\"\n-\ttest -n \"$strategy_opts\" && strategy_opts=\"--strategy-opts=$strategy_opts\"\n-\ttest -n \"$switch_to\" && switch_to=\"--switch-to=$switch_to\"\n-\ttest -n \"$cmd\" && cmd=\"--cmd=$cmd\"\n-\ttest -n \"$action\" && action=\"--$action\"\n-\n-\texec git rebase--interactive \"$action\" \"$keep_empty\" \"$rebase_merges\" \"$rebase_cousins\" \\\n-\t\t\"$upstream\" \"$onto\" \"$squash_onto\" \"$restrict_revision\" \\\n-\t\t\"$allow_empty_message\" \"$autosquash\" \"$verbose\" \\\n-\t\t\"$force_rebase\" \"$onto_name\" \"$head_name\" \"$strategy\" \\\n-\t\t\"$strategy_opts\" \"$cmd\" \"$switch_to\" \\\n-\t\t\"$allow_rerere_autoupdate\" \"$gpg_sign_opt\" \"$signoff\" \\\n-\t\t\"$reschedule_failed_exec\"\n-}\n-\n-run_specific_rebase () {\n-\tif [ \"$interactive_rebase\" = implied ]; then\n-\t\tGIT_SEQUENCE_EDITOR=:\n-\t\texport GIT_SEQUENCE_EDITOR\n-\t\tautosquash=\n-\tfi\n-\n-\tif test -n \"$interactive_rebase\" -a -z \"$preserve_merges\"\n-\tthen\n-\t\trun_interactive\n-\telse\n-\t\t. git-rebase--$type\n-\n-\t\tif test -z \"$preserve_merges\"\n-\t\tthen\n-\t\t\tgit_rebase__$type\n-\t\telse\n-\t\t\tgit_rebase__preserve_merges\n-\t\tfi\n-\tfi\n-\n-\tret=$?\n-\tif test $ret -eq 0\n-\tthen\n-\t\tfinish_rebase\n-\telif test $ret -eq 2 # special exit status for rebase -p\n-\tthen\n-\t\tapply_autostash &&\n-\t\trm -rf \"$state_dir\" &&\n-\t\tdie \"Nothing to do\"\n-\tfi\n-\texit $ret\n-}\n-\n-run_pre_rebase_hook () {\n-\tif test -z \"$ok_to_skip_pre_rebase\" &&\n-\t   test -x \"$(git rev-parse --git-path hooks/pre-rebase)\"\n-\tthen\n-\t\t\"$(git rev-parse --git-path hooks/pre-rebase)\" ${1+\"$@\"} ||\n-\t\tdie \"$(gettext \"The pre-rebase hook refused to rebase.\")\"\n-\tfi\n-}\n-\n-test -f \"$apply_dir\"/applying &&\n-\tdie \"$(gettext \"It looks like 'git am' is in progress. Cannot rebase.\")\"\n-\n-if test -d \"$apply_dir\"\n-then\n-\ttype=am\n-\tstate_dir=\"$apply_dir\"\n-elif test -d \"$merge_dir\"\n-then\n-\ttype=interactive\n-\tif test -d \"$merge_dir\"/rewritten\n-\tthen\n-\t\ttype=preserve-merges\n-\t\tinteractive_rebase=explicit\n-\t\tpreserve_merges=t\n-\telif test -f \"$merge_dir\"/interactive\n-\tthen\n-\t\tinteractive_rebase=explicit\n-\tfi\n-\tstate_dir=\"$merge_dir\"\n-fi\n-test -n \"$type\" && in_progress=t\n-\n-total_argc=$#\n-while test $# != 0\n-do\n-\tcase \"$1\" in\n-\t--no-verify)\n-\t\tok_to_skip_pre_rebase=yes\n-\t\t;;\n-\t--verify)\n-\t\tok_to_skip_pre_rebase=\n-\t\t;;\n-\t--continue|--skip|--abort|--quit|--edit-todo|--show-current-patch)\n-\t\ttest $total_argc -eq 2 || usage\n-\t\taction=${1##--}\n-\t\t;;\n-\t--onto=*)\n-\t\tonto=\"${1#--onto=}\"\n-\t\t;;\n-\t--exec=*)\n-\t\tcmd=\"${cmd}exec ${1#--exec=}${LF}\"\n-\t\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n-\t\t;;\n-\t--interactive)\n-\t\tinteractive_rebase=explicit\n-\t\t;;\n-\t--keep-empty)\n-\t\tkeep_empty=yes\n-\t\t;;\n-\t--allow-empty-message)\n-\t\tallow_empty_message=--allow-empty-message\n-\t\t;;\n-\t--no-keep-empty)\n-\t\tkeep_empty=\n-\t\t;;\n-\t--rebase-merges)\n-\t\trebase_merges=t\n-\t\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n-\t\t;;\n-\t--rebase-merges=*)\n-\t\trebase_merges=t\n-\t\tcase \"${1#*=}\" in\n-\t\trebase-cousins) rebase_cousins=t;;\n-\t\tno-rebase-cousins) rebase_cousins=;;\n-\t\t*) die \"Unknown mode: $1\";;\n-\t\tesac\n-\t\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n-\t\t;;\n-\t--preserve-merges)\n-\t\tpreserve_merges=t\n-\t\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n-\t\t;;\n-\t--autosquash)\n-\t\tautosquash=t\n-\t\t;;\n-\t--no-autosquash)\n-\t\tautosquash=\n-\t\t;;\n-\t--fork-point)\n-\t\tfork_point=t\n-\t\t;;\n-\t--no-fork-point)\n-\t\tfork_point=\n-\t\t;;\n-\t--merge)\n-\t\tdo_merge=t\n-\t\t;;\n-\t--strategy-option=*)\n-\t\tstrategy_opts=\"$strategy_opts $(git rev-parse --sq-quote \"--${1#--strategy-option=}\" | sed -e s/^.//)\"\n-\t\tdo_merge=t\n-\t\ttest -z \"$strategy\" && strategy=recursive\n-\t\t;;\n-\t--strategy=*)\n-\t\tstrategy=\"${1#--strategy=}\"\n-\t\tdo_merge=t\n-\t\t;;\n-\t--no-stat)\n-\t\tdiffstat=\n-\t\t;;\n-\t--stat)\n-\t\tdiffstat=t\n-\t\t;;\n-\t--autostash)\n-\t\tautostash=true\n-\t\t;;\n-\t--no-autostash)\n-\t\tautostash=false\n-\t\t;;\n-\t--verbose)\n-\t\tverbose=t\n-\t\tdiffstat=t\n-\t\tGIT_QUIET=\n-\t\t;;\n-\t--quiet)\n-\t\tGIT_QUIET=t\n-\t\tgit_am_opt=\"$git_am_opt -q\"\n-\t\tverbose=\n-\t\tdiffstat=\n-\t\t;;\n-\t--whitespace=*)\n-\t\tgit_am_opt=\"$git_am_opt --whitespace=${1#--whitespace=}\"\n-\t\tcase \"${1#--whitespace=}\" in\n-\t\tfix|strip)\n-\t\t\tforce_rebase=t\n-\t\t\t;;\n-\t\twarn|nowarn|error|error-all)\n-\t\t\t;; # okay, known whitespace option\n-\t\t*)\n-\t\t\tdie \"fatal: Invalid whitespace option: '${1#*=}'\"\n-\t\t\t;;\n-\t\tesac\n-\t\t;;\n-\t--ignore-whitespace)\n-\t\tgit_am_opt=\"$git_am_opt $1\"\n-\t\t;;\n-\t--signoff)\n-\t\tsignoff=--signoff\n-\t\t;;\n-\t--no-signoff)\n-\t\tsignoff=\n-\t\t;;\n-\t--committer-date-is-author-date|--ignore-date)\n-\t\tgit_am_opt=\"$git_am_opt $1\"\n-\t\tforce_rebase=t\n-\t\t;;\n-\t-C*[!0-9]*)\n-\t\tdie \"fatal: switch \\`C' expects a numerical value\"\n-\t\t;;\n-\t-C*)\n-\t\tgit_am_opt=\"$git_am_opt $1\"\n-\t\t;;\n-\t--root)\n-\t\trebase_root=t\n-\t\t;;\n-\t--force-rebase|--no-ff)\n-\t\tforce_rebase=t\n-\t\t;;\n-\t--rerere-autoupdate|--no-rerere-autoupdate)\n-\t\tallow_rerere_autoupdate=\"$1\"\n-\t\t;;\n-\t--gpg-sign)\n-\t\tgpg_sign_opt=-S\n-\t\t;;\n-\t--gpg-sign=*)\n-\t\tgpg_sign_opt=\"-S${1#--gpg-sign=}\"\n-\t\t;;\n-\t--reschedule-failed-exec)\n-\t\treschedule_failed_exec=--reschedule-failed-exec\n-\t\t;;\n-\t--no-reschedule-failed-exec)\n-\t\treschedule_failed_exec=\n-\t\t;;\n-\t--)\n-\t\tshift\n-\t\tbreak\n-\t\t;;\n-\t*)\n-\t\tusage\n-\t\t;;\n-\tesac\n-\tshift\n-done\n-test $# -gt 2 && usage\n-\n-if test -n \"$action\"\n-then\n-\ttest -z \"$in_progress\" && die \"$(gettext \"No rebase in progress?\")\"\n-\t# Only interactive rebase uses detailed reflog messages\n-\tif test -n \"$interactive_rebase\" && test \"$GIT_REFLOG_ACTION\" = rebase\n-\tthen\n-\t\tGIT_REFLOG_ACTION=\"rebase -i ($action)\"\n-\t\texport GIT_REFLOG_ACTION\n-\tfi\n-fi\n-\n-if test \"$action\" = \"edit-todo\" && test -z \"$interactive_rebase\"\n-then\n-\tdie \"$(gettext \"The --edit-todo action can only be used during interactive rebase.\")\"\n-fi\n-\n-case \"$action\" in\n-continue)\n-\t# Sanity check\n-\tgit rev-parse --verify HEAD >/dev/null ||\n-\t\tdie \"$(gettext \"Cannot read HEAD\")\"\n-\tgit update-index --ignore-submodules --refresh &&\n-\tgit diff-files --quiet --ignore-submodules || {\n-\t\techo \"$(gettext \"You must edit all merge conflicts and then\n-mark them as resolved using git add\")\"\n-\t\texit 1\n-\t}\n-\tread_basic_state\n-\trun_specific_rebase\n-\t;;\n-skip)\n-\toutput git reset --hard HEAD || exit $?\n-\tread_basic_state\n-\trun_specific_rebase\n-\t;;\n-abort)\n-\tgit rerere clear\n-\tread_basic_state\n-\tcase \"$head_name\" in\n-\trefs/*)\n-\t\tgit symbolic-ref -m \"rebase: aborting\" HEAD $head_name ||\n-\t\tdie \"$(eval_gettext \"Could not move back to \\$head_name\")\"\n-\t\t;;\n-\tesac\n-\toutput git reset --hard $orig_head\n-\tfinish_rebase\n-\texit\n-\t;;\n-quit)\n-\texec rm -rf \"$state_dir\"\n-\t;;\n-edit-todo)\n-\trun_specific_rebase\n-\t;;\n-show-current-patch)\n-\trun_specific_rebase\n-\tdie \"BUG: run_specific_rebase is not supposed to return here\"\n-\t;;\n-esac\n-\n-# Make sure no rebase is in progress\n-if test -n \"$in_progress\"\n-then\n-\tstate_dir_base=${state_dir##*/}\n-\tcmd_live_rebase=\"git rebase (--continue | --abort | --skip)\"\n-\tcmd_clear_stale_rebase=\"rm -fr \\\"$state_dir\\\"\"\n-\tdie \"\n-$(eval_gettext 'It seems that there is already a $state_dir_base directory, and\n-I wonder if you are in the middle of another rebase.  If that is the\n-case, please try\n-\t$cmd_live_rebase\n-If that is not the case, please\n-\t$cmd_clear_stale_rebase\n-and run me again.  I am stopping in case you still have something\n-valuable there.')\"\n-fi\n-\n-if test -n \"$rebase_root\" && test -z \"$onto\"\n-then\n-\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n-fi\n-\n-if test -n \"$keep_empty\"\n-then\n-\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n-fi\n-\n-actually_interactive=\n-if test -n \"$interactive_rebase\"\n-then\n-\tif test -z \"$preserve_merges\"\n-\tthen\n-\t\ttype=interactive\n-\telse\n-\t\ttype=preserve-merges\n-\tfi\n-\tactually_interactive=t\n-\tstate_dir=\"$merge_dir\"\n-elif test -n \"$do_merge\"\n-then\n-\tinteractive_rebase=implied\n-\ttype=interactive\n-\tstate_dir=\"$merge_dir\"\n-else\n-\ttype=am\n-\tstate_dir=\"$apply_dir\"\n-fi\n-\n-if test -t 2 && test -z \"$GIT_QUIET\"\n-then\n-\tgit_format_patch_opt=\"$git_format_patch_opt --progress\"\n-fi\n-\n-incompatible_opts=$(echo \" $git_am_opt \" | \\\n-\t\t    sed -e 's/ -q / /g' -e 's/^ \\(.*\\) $/\\1/')\n-if test -n \"$incompatible_opts\"\n-then\n-\tif test -n \"$actually_interactive\" || test \"$do_merge\"\n-\tthen\n-\t\tdie \"$(gettext \"fatal: cannot combine am options with either interactive or merge options\")\"\n-\tfi\n-fi\n-\n-if test -n \"$signoff\"\n-then\n-\ttest -n \"$preserve_merges\" &&\n-\t\tdie \"$(gettext \"fatal: cannot combine '--signoff' with '--preserve-merges'\")\"\n-\tgit_am_opt=\"$git_am_opt $signoff\"\n-\tforce_rebase=t\n-fi\n-\n-if test -n \"$preserve_merges\"\n-then\n-\t# Note: incompatibility with --signoff handled in signoff block above\n-\t# Note: incompatibility with --interactive is just a strong warning;\n-\t#       git-rebase.txt caveats with \"unless you know what you are doing\"\n-\ttest -n \"$rebase_merges\" &&\n-\t\tdie \"$(gettext \"fatal: cannot combine '--preserve-merges' with '--rebase-merges'\")\"\n-\n-\ttest -n \"$reschedule_failed_exec\" &&\n-\t\tdie \"$(gettext \"error: cannot combine '--preserve-merges' with '--reschedule-failed-exec'\")\"\n-fi\n-\n-if test -n \"$rebase_merges\"\n-then\n-\ttest -n \"$strategy_opts\" &&\n-\t\tdie \"$(gettext \"fatal: cannot combine '--rebase-merges' with '--strategy-option'\")\"\n-\ttest -n \"$strategy\" &&\n-\t\tdie \"$(gettext \"fatal: cannot combine '--rebase-merges' with '--strategy'\")\"\n-fi\n-\n-if test -z \"$rebase_root\"\n-then\n-\tcase \"$#\" in\n-\t0)\n-\t\tif ! upstream_name=$(git rev-parse --symbolic-full-name \\\n-\t\t\t--verify -q @{upstream} 2>/dev/null)\n-\t\tthen\n-\t\t\t. git-parse-remote\n-\t\t\terror_on_missing_default_upstream \"rebase\" \"rebase\" \\\n-\t\t\t\t\"against\" \"git rebase $(gettext '<branch>')\"\n-\t\tfi\n-\n-\t\ttest \"$fork_point\" = auto && fork_point=t\n-\t\t;;\n-\t*)\tupstream_name=\"$1\"\n-\t\tif test \"$upstream_name\" = \"-\"\n-\t\tthen\n-\t\t\tupstream_name=\"@{-1}\"\n-\t\tfi\n-\t\tshift\n-\t\t;;\n-\tesac\n-\tupstream=$(peel_committish \"${upstream_name}\") ||\n-\tdie \"$(eval_gettext \"invalid upstream '\\$upstream_name'\")\"\n-\tupstream_arg=\"$upstream_name\"\n-else\n-\tif test -z \"$onto\"\n-\tthen\n-\t\tempty_tree=$(git hash-object -t tree /dev/null)\n-\t\tonto=$(git commit-tree $empty_tree </dev/null)\n-\t\tsquash_onto=\"$onto\"\n-\tfi\n-\tunset upstream_name\n-\tunset upstream\n-\ttest $# -gt 1 && usage\n-\tupstream_arg=--root\n-fi\n-\n-# Make sure the branch to rebase onto is valid.\n-onto_name=${onto-\"$upstream_name\"}\n-case \"$onto_name\" in\n-*...*)\n-\tif\tleft=${onto_name%...*} right=${onto_name#*...} &&\n-\t\tonto=$(git merge-base --all ${left:-HEAD} ${right:-HEAD})\n-\tthen\n-\t\tcase \"$onto\" in\n-\t\t?*\"$LF\"?*)\n-\t\t\tdie \"$(eval_gettext \"\\$onto_name: there are more than one merge bases\")\"\n-\t\t\t;;\n-\t\t'')\n-\t\t\tdie \"$(eval_gettext \"\\$onto_name: there is no merge base\")\"\n-\t\t\t;;\n-\t\tesac\n-\telse\n-\t\tdie \"$(eval_gettext \"\\$onto_name: there is no merge base\")\"\n-\tfi\n-\t;;\n-*)\n-\tonto=$(peel_committish \"$onto_name\") ||\n-\tdie \"$(eval_gettext \"Does not point to a valid commit: \\$onto_name\")\"\n-\t;;\n-esac\n-\n-# If the branch to rebase is given, that is the branch we will rebase\n-# $branch_name -- branch/commit being rebased, or HEAD (already detached)\n-# $orig_head -- commit object name of tip of the branch before rebasing\n-# $head_name -- refs/heads/<that-branch> or \"detached HEAD\"\n-switch_to=\n-case \"$#\" in\n-1)\n-\t# Is it \"rebase other $branchname\" or \"rebase other $commit\"?\n-\tbranch_name=\"$1\"\n-\tswitch_to=\"$1\"\n-\n-\t# Is it a local branch?\n-\tif git show-ref --verify --quiet -- \"refs/heads/$branch_name\" &&\n-\t   orig_head=$(git rev-parse -q --verify \"refs/heads/$branch_name\")\n-\tthen\n-\t\thead_name=\"refs/heads/$branch_name\"\n-\t# If not is it a valid ref (branch or commit)?\n-\telif orig_head=$(git rev-parse -q --verify \"$branch_name\")\n-\tthen\n-\t\thead_name=\"detached HEAD\"\n-\n-\telse\n-\t\tdie \"$(eval_gettext \"fatal: no such branch/commit '\\$branch_name'\")\"\n-\tfi\n-\t;;\n-0)\n-\t# Do not need to switch branches, we are already on it.\n-\tif branch_name=$(git symbolic-ref -q HEAD)\n-\tthen\n-\t\thead_name=$branch_name\n-\t\tbranch_name=$(expr \"z$branch_name\" : 'zrefs/heads/\\(.*\\)')\n-\telse\n-\t\thead_name=\"detached HEAD\"\n-\t\tbranch_name=HEAD\n-\tfi\n-\torig_head=$(git rev-parse --verify HEAD) || exit\n-\t;;\n-*)\n-\tdie \"BUG: unexpected number of arguments left to parse\"\n-\t;;\n-esac\n-\n-if test \"$fork_point\" = t\n-then\n-\tnew_upstream=$(git merge-base --fork-point \"$upstream_name\" \\\n-\t\t\t\"${switch_to:-HEAD}\")\n-\tif test -n \"$new_upstream\"\n-\tthen\n-\t\trestrict_revision=$new_upstream\n-\tfi\n-fi\n-\n-if test \"$autostash\" = true && ! (require_clean_work_tree) 2>/dev/null\n-then\n-\tstash_sha1=$(git stash create \"autostash\") ||\n-\tdie \"$(gettext 'Cannot autostash')\"\n-\n-\tmkdir -p \"$state_dir\" &&\n-\techo $stash_sha1 >\"$state_dir/autostash\" &&\n-\tstash_abbrev=$(git rev-parse --short $stash_sha1) &&\n-\techo \"$(eval_gettext 'Created autostash: $stash_abbrev')\" &&\n-\tgit reset --hard\n-fi\n-\n-require_clean_work_tree \"rebase\" \"$(gettext \"Please commit or stash them.\")\"\n-\n-# Now we are rebasing commits $upstream..$orig_head (or with --root,\n-# everything leading up to $orig_head) on top of $onto\n-\n-# Check if we are already based on $onto with linear history,\n-# but this should be done only when upstream and onto are the same\n-# and if this is not an interactive rebase.\n-mb=$(git merge-base \"$onto\" \"$orig_head\")\n-if test -z \"$actually_interactive\" && test \"$upstream\" = \"$onto\" &&\n-\ttest \"$mb\" = \"$onto\" && test -z \"$restrict_revision\" &&\n-\t# linear history?\n-\t! (git rev-list --parents \"$onto\"..\"$orig_head\" | sane_grep \" .* \") > /dev/null\n-then\n-\tif test -z \"$force_rebase\"\n-\tthen\n-\t\t# Lazily switch to the target branch if needed...\n-\t\ttest -z \"$switch_to\" ||\n-\t\tGIT_REFLOG_ACTION=\"$GIT_REFLOG_ACTION: checkout $switch_to\" \\\n-\t\t\tgit checkout -q \"$switch_to\" --\n-\t\tif test \"$branch_name\" = \"HEAD\" &&\n-\t\t\t ! git symbolic-ref -q HEAD\n-\t\tthen\n-\t\t\tsay \"$(eval_gettext \"HEAD is up to date.\")\"\n-\t\telse\n-\t\t\tsay \"$(eval_gettext \"Current branch \\$branch_name is up to date.\")\"\n-\t\tfi\n-\t\tfinish_rebase\n-\t\texit 0\n-\telse\n-\t\tif test \"$branch_name\" = \"HEAD\" &&\n-\t\t\t ! git symbolic-ref -q HEAD\n-\t\tthen\n-\t\t\tsay \"$(eval_gettext \"HEAD is up to date, rebase forced.\")\"\n-\t\telse\n-\t\t\tsay \"$(eval_gettext \"Current branch \\$branch_name is up to date, rebase forced.\")\"\n-\t\tfi\n-\tfi\n-fi\n-\n-# If a hook exists, give it a chance to interrupt\n-run_pre_rebase_hook \"$upstream_arg\" \"$@\"\n-\n-if test -n \"$diffstat\"\n-then\n-\tif test -n \"$verbose\"\n-\tthen\n-\t\tif test -z \"$mb\"\n-\t\tthen\n-\t\t\techo \"$(eval_gettext \"Changes to \\$onto:\")\"\n-\t\telse\n-\t\t\techo \"$(eval_gettext \"Changes from \\$mb to \\$onto:\")\"\n-\t\tfi\n-\tfi\n-\tmb_tree=\"${mb:-$(git hash-object -t tree /dev/null)}\"\n-\t# We want color (if set), but no pager\n-\tGIT_PAGER='' git diff --stat --summary \"$mb_tree\" \"$onto\"\n-fi\n-\n-if test -z \"$actually_interactive\" && test \"$mb\" = \"$orig_head\"\n-then\n-\tsay \"$(eval_gettext \"Fast-forwarded \\$branch_name to \\$onto_name.\")\"\n-\tGIT_REFLOG_ACTION=\"$GIT_REFLOG_ACTION: checkout $onto_name\" \\\n-\t\tgit checkout -q \"$onto^0\" || die \"could not detach HEAD\"\n-\t# If the $onto is a proper descendant of the tip of the branch, then\n-\t# we just fast-forwarded.\n-\tgit update-ref ORIG_HEAD $orig_head\n-\tmove_to_original_branch\n-\tfinish_rebase\n-\texit 0\n-fi\n-\n-test -n \"$interactive_rebase\" && run_specific_rebase\n-\n-# Detach HEAD and reset the tree\n-say \"$(gettext \"First, rewinding head to replay your work on top of it...\")\"\n-\n-GIT_REFLOG_ACTION=\"$GIT_REFLOG_ACTION: checkout $onto_name\" \\\n-\tgit checkout -q \"$onto^0\" || die \"could not detach HEAD\"\n-git update-ref ORIG_HEAD $orig_head\n-\n-if test -n \"$rebase_root\"\n-then\n-\trevisions=\"$onto..$orig_head\"\n-else\n-\trevisions=\"${restrict_revision-$upstream}..$orig_head\"\n-fi\n-\n-run_specific_rebase\ndiff --git a/t/README b/t/README\nindex 7a3d582267c..385262357b5 100644\n--- a/t/README\n+++ b/t/README\n@@ -379,10 +379,6 @@ the --no-sparse command-line argument.\n GIT_TEST_PRELOAD_INDEX=<boolean> exercises the preload-index code path\n by overriding the minimum number of cache entries required per thread.\n \n-GIT_TEST_REBASE_USE_BUILTIN=<boolean>, when false, disables the\n-builtin version of git-rebase. See 'rebase.useBuiltin' in\n-git-config(1).\n-\n GIT_TEST_INDEX_THREADS=<n> enables exercising the multi-threaded loading\n of the index for the whole test suite by bypassing the default number of\n cache entries and thread minimums. Setting this to 1 will make the\ndiff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh\nindex 3e73f7584ce..a809de93047 100755\n--- a/t/t3400-rebase.sh\n+++ b/t/t3400-rebase.sh\n@@ -311,4 +311,20 @@ test_expect_success 'rebase--merge.sh and --show-current-patch' '\n \t)\n '\n \n+test_expect_success 'rebase -c rebase.useBuiltin=false warning' '\n+\texpected=\"rebase.useBuiltin support has been removed\" &&\n+\n+\t# Only warn when the legacy rebase is requested...\n+\ttest_must_fail git -c rebase.useBuiltin=false rebase 2>err &&\n+\ttest_i18ngrep \"$expected\" err &&\n+\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=false git rebase 2>err &&\n+\ttest_i18ngrep \"$expected\" err &&\n+\n+\t# ...not when we would have used the built-in anyway\n+\ttest_must_fail git -c rebase.useBuiltin=true rebase 2>err &&\n+\ttest_must_be_empty err &&\n+\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=true git rebase 2>err &&\n+\ttest_must_be_empty err\n+'\n+\n test_done\ndiff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\nindex b60b11f9f2f..1723e1a8585 100755\n--- a/t/t3404-rebase-interactive.sh\n+++ b/t/t3404-rebase-interactive.sh\n@@ -149,12 +149,10 @@ test_expect_success 'rebase -i with the exec command checks tree cleanness' '\n \n test_expect_success 'rebase -x with empty command fails' '\n \ttest_when_finished \"git rebase --abort ||:\" &&\n-\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=true \\\n-\t\tgit rebase -x \"\" @ 2>actual &&\n+\ttest_must_fail env git rebase -x \"\" @ 2>actual &&\n \ttest_write_lines \"error: empty exec command\" >expected &&\n \ttest_i18ncmp expected actual &&\n-\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=true \\\n-\t\tgit rebase -x \" \" @ 2>actual &&\n+\ttest_must_fail env git rebase -x \" \" @ 2>actual &&\n \ttest_i18ncmp expected actual\n '\n \n@@ -162,8 +160,7 @@ LF='\n '\n test_expect_success 'rebase -x with newline in command fails' '\n \ttest_when_finished \"git rebase --abort ||:\" &&\n-\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=true \\\n-\t\tgit rebase -x \"a${LF}b\" @ 2>actual &&\n+\ttest_must_fail env git rebase -x \"a${LF}b\" @ 2>actual &&\n \ttest_write_lines \"error: exec commands cannot contain newlines\" \\\n \t\t\t >expected &&\n \ttest_i18ncmp expected actual\n-- \n2.21.0.360.g471c308f928\n\n"},{"id":"371898","messageId":"d0b21fb8-edc1-cc48-7d5f-2ec4bbbb4aab@gmail.com","threadId":"50341","inReplyTo":"20190318110152.27246-1-avarab@gmail.com","subject":"Re: [PATCH v4] rebase: remove the rebase.useBuiltin setting","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2019-03-19T10:21:38Z","receivedAt":"2019-03-19T10:21:55Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Ævar\nOn 18/03/2019 11:01, Ævar Arnfjörð Bjarmason wrote:\n> Remove the rebase.useBuiltin setting, which was added as an escape\n> hatch to disable the builtin version of rebase first released with Git\n> 2.20.\n> \n> See [1] for the initial implementation of rebase.useBuiltin, and [2]\n> and [3] for the documentation and corresponding\n> GIT_TEST_REBASE_USE_BUILTIN option.\n> \n> Carrying the legacy version is a maintenance burden as seen in\n> 7e097e27d3 (\"legacy-rebase: backport -C<n> and --whitespace=<option>\n> checks\", 2018-11-20) and 9aea5e9286 (\"rebase: fix regression in\n> rebase.useBuiltin=false test mode\", 2019-02-13). Since the built-in\n> version has been shown to be stable enough let's remove the legacy\n> version.\n> \n> As noted in [3] having use_builtin_rebase() shell out to get its\n> config doesn't make any sense anymore, that was done for the purposes\n> of spawning the legacy rebase without having modified any global\n> state. Let's instead handle this case in rebase_config().\n> \n> There's still a bunch of references to git-legacy-rebase in po/*.po,\n> but those will be dealt with in time by the i18n effort.\n> \n> Even though this configuration variable only existed two releases\n> let's not entirely delete the entry from the docs, but note its\n> absence. Individual versions of git tend to be around for a while due\n> to distro packaging timelines, so e.g. if we're \"lucky\" a given\n> version like 2.21 might be installed on say OSX for half a decade.\n> \n> That'll mean some people probably setting this in config, and then\n> when they later wonder if it's needed they can Google search the\n> config option name or check it in git-config. It also allows us to\n> refer to the docs from the warning for details.\n> \n> 1. 55071ea248 (\"rebase: start implementing it as a builtin\",\n>     2018-08-07)\n> 2. d8d0a546f0 (\"rebase doc: document rebase.useBuiltin\", 2018-11-14)\n> 3. 62c23938fa (\"tests: add a special setup where rebase.useBuiltin is\n>     off\", 2018-11-14)\n> 3. https://public-inbox.org/git/nycvar.QRO.7.76.6.1903141544110.41@tvgsbejvaqbjf.bet/\n> \n> Acked-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n> ---\n> \n> Fix wording issues pointed out by Phillip & incorporated the Acked-by\n> in Junio's push-out & added my SOB.\n> \n> The confusion with \"one release\" was a) I'd initially written this\n> before 2.21 was cut and forgot to change that\n\nAh I wondered if that was the case. The new version looks great\n\nThanks\n\nPhillip\n\n  2) I was then using\n> \"between\" in the inclusive sense \"pick a number between 1 and\n> 10\". Phillip's suggestion is better.\n> \n> Range-diff:\n> 1:  799dd15e4fd ! 1:  9ca747cb1f5 rebase: remove the rebase.useBuiltin setting\n>      @@ -25,7 +25,7 @@\n>           There's still a bunch of references to git-legacy-rebase in po/*.po,\n>           but those will be dealt with in time by the i18n effort.\n>       \n>      -    Even though this configuration variable only existed for one release\n>      +    Even though this configuration variable only existed two releases\n>           let's not entirely delete the entry from the docs, but note its\n>           absence. Individual versions of git tend to be around for a while due\n>           to distro packaging timelines, so e.g. if we're \"lucky\" a given\n>      @@ -43,6 +43,9 @@\n>              off\", 2018-11-14)\n>           3. https://public-inbox.org/git/nycvar.QRO.7.76.6.1903141544110.41@tvgsbejvaqbjf.bet/\n>       \n>      +    Acked-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n>      +    Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n>      +\n>        diff --git a/.gitignore b/.gitignore\n>        --- a/.gitignore\n>        +++ b/.gitignore\n>      @@ -72,8 +75,8 @@\n>       -If you find some reason to set this option to `false` other than\n>       -one-off testing you should report the behavior difference as a bug in\n>       -git.\n>      -+\tUnused configuration variable. Used between Git version 2.20\n>      -+\tand 2.21 as an escape hatch to enable the legacy shellscript\n>      ++\tUnused configuration variable. Used in Git versions 2.20 and\n>      ++\t2.21 as an escape hatch to enable the legacy shellscript\n>       +\timplementation of rebase. Now the built-in rewrite of it in C\n>       +\tis always used. Setting this will emit a warning, to alert any\n>       +\tremaining users that setting this now does nothing.\n> \n>   .gitignore                      |   1 -\n>   Documentation/config/rebase.txt |  17 +-\n>   Makefile                        |   1 -\n>   builtin/rebase.c                |  50 +--\n>   git-legacy-rebase.sh            | 770 --------------------------------\n>   t/README                        |   4 -\n>   t/t3400-rebase.sh               |  16 +\n>   t/t3404-rebase-interactive.sh   |   9 +-\n>   8 files changed, 35 insertions(+), 833 deletions(-)\n>   delete mode 100755 git-legacy-rebase.sh\n> \n> diff --git a/.gitignore b/.gitignore\n> index 7374587f9df..5cb84f1d1a9 100644\n> --- a/.gitignore\n> +++ b/.gitignore\n> @@ -82,7 +82,6 @@\n>   /git-init-db\n>   /git-interpret-trailers\n>   /git-instaweb\n> -/git-legacy-rebase\n>   /git-log\n>   /git-ls-files\n>   /git-ls-remote\n> diff --git a/Documentation/config/rebase.txt b/Documentation/config/rebase.txt\n> index 331d250e046..d98e32d812e 100644\n> --- a/Documentation/config/rebase.txt\n> +++ b/Documentation/config/rebase.txt\n> @@ -1,16 +1,9 @@\n>   rebase.useBuiltin::\n> -\tSet to `false` to use the legacy shellscript implementation of\n> -\tlinkgit:git-rebase[1]. Is `true` by default, which means use\n> -\tthe built-in rewrite of it in C.\n> -+\n> -The C rewrite is first included with Git version 2.20. This option\n> -serves an an escape hatch to re-enable the legacy version in case any\n> -bugs are found in the rewrite. This option and the shellscript version\n> -of linkgit:git-rebase[1] will be removed in some future release.\n> -+\n> -If you find some reason to set this option to `false` other than\n> -one-off testing you should report the behavior difference as a bug in\n> -git.\n> +\tUnused configuration variable. Used in Git versions 2.20 and\n> +\t2.21 as an escape hatch to enable the legacy shellscript\n> +\timplementation of rebase. Now the built-in rewrite of it in C\n> +\tis always used. Setting this will emit a warning, to alert any\n> +\tremaining users that setting this now does nothing.\n>   \n>   rebase.stat::\n>   \tWhether to show a diffstat of what changed upstream since the last\n> diff --git a/Makefile b/Makefile\n> index 537493822b1..9f1159cffcb 100644\n> --- a/Makefile\n> +++ b/Makefile\n> @@ -632,7 +632,6 @@ SCRIPT_SH += git-merge-one-file.sh\n>   SCRIPT_SH += git-merge-resolve.sh\n>   SCRIPT_SH += git-mergetool.sh\n>   SCRIPT_SH += git-quiltimport.sh\n> -SCRIPT_SH += git-legacy-rebase.sh\n>   SCRIPT_SH += git-remote-testgit.sh\n>   SCRIPT_SH += git-request-pull.sh\n>   SCRIPT_SH += git-stash.sh\n> diff --git a/builtin/rebase.c b/builtin/rebase.c\n> index 52114cbf0d9..bc3dc629c16 100644\n> --- a/builtin/rebase.c\n> +++ b/builtin/rebase.c\n> @@ -46,29 +46,6 @@ enum rebase_type {\n>   \tREBASE_PRESERVE_MERGES\n>   };\n>   \n> -static int use_builtin_rebase(void)\n> -{\n> -\tstruct child_process cp = CHILD_PROCESS_INIT;\n> -\tstruct strbuf out = STRBUF_INIT;\n> -\tint ret, env = git_env_bool(\"GIT_TEST_REBASE_USE_BUILTIN\", -1);\n> -\n> -\tif (env != -1)\n> -\t\treturn env;\n> -\n> -\targv_array_pushl(&cp.args,\n> -\t\t\t \"config\", \"--bool\", \"rebase.usebuiltin\", NULL);\n> -\tcp.git_cmd = 1;\n> -\tif (capture_command(&cp, &out, 6)) {\n> -\t\tstrbuf_release(&out);\n> -\t\treturn 1;\n> -\t}\n> -\n> -\tstrbuf_trim(&out);\n> -\tret = !strcmp(\"true\", out.buf);\n> -\tstrbuf_release(&out);\n> -\treturn ret;\n> -}\n> -\n>   struct rebase_options {\n>   \tenum rebase_type type;\n>   \tconst char *state_dir;\n> @@ -106,6 +83,7 @@ struct rebase_options {\n>   \tchar *strategy, *strategy_opts;\n>   \tstruct strbuf git_format_patch_opt;\n>   \tint reschedule_failed_exec;\n> +\tint use_legacy_rebase;\n>   };\n>   \n>   static int is_interactive(struct rebase_options *opts)\n> @@ -869,6 +847,11 @@ static int rebase_config(const char *var, const char *value, void *data)\n>   \t\treturn 0;\n>   \t}\n>   \n> +\tif (!strcmp(var, \"rebase.usebuiltin\")) {\n> +\t\topts->use_legacy_rebase = !git_config_bool(var, value);\n> +\t\treturn 0;\n> +\t}\n> +\n>   \treturn git_default_config(var, value, data);\n>   }\n>   \n> @@ -1143,22 +1126,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>   \t};\n>   \tint i;\n>   \n> -\t/*\n> -\t * NEEDSWORK: Once the builtin rebase has been tested enough\n> -\t * and git-legacy-rebase.sh is retired to contrib/, this preamble\n> -\t * can be removed.\n> -\t */\n> -\n> -\tif (!use_builtin_rebase()) {\n> -\t\tconst char *path = mkpath(\"%s/git-legacy-rebase\",\n> -\t\t\t\t\t  git_exec_path());\n> -\n> -\t\tif (sane_execvp(path, (char **)argv) < 0)\n> -\t\t\tdie_errno(_(\"could not exec %s\"), path);\n> -\t\telse\n> -\t\t\tBUG(\"sane_execvp() returned???\");\n> -\t}\n> -\n>   \tif (argc == 2 && !strcmp(argv[1], \"-h\"))\n>   \t\tusage_with_options(builtin_rebase_usage,\n>   \t\t\t\t   builtin_rebase_options);\n> @@ -1169,6 +1136,11 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>   \n>   \tgit_config(rebase_config, &options);\n>   \n> +\tif (options.use_legacy_rebase ||\n> +\t    !git_env_bool(\"GIT_TEST_REBASE_USE_BUILTIN\", -1))\n> +\t\twarning(_(\"the rebase.useBuiltin support has been removed!\\n\"\n> +\t\t\t  \"See its entry in 'git help config' for details.\"));\n> +\n>   \tstrbuf_reset(&buf);\n>   \tstrbuf_addf(&buf, \"%s/applying\", apply_dir());\n>   \tif(file_exists(buf.buf))\n> diff --git a/git-legacy-rebase.sh b/git-legacy-rebase.sh\n> deleted file mode 100755\n> index 5c2c4e5276d..00000000000\n> --- a/git-legacy-rebase.sh\n> +++ /dev/null\n> @@ -1,770 +0,0 @@\n> -#!/bin/sh\n> -#\n> -# Copyright (c) 2005 Junio C Hamano.\n> -#\n> -\n> -SUBDIRECTORY_OK=Yes\n> -OPTIONS_KEEPDASHDASH=\n> -OPTIONS_STUCKLONG=t\n> -OPTIONS_SPEC=\"\\\n> -git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] [<upstream>] [<branch>]\n> -git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] --root [<branch>]\n> -git rebase --continue | --abort | --skip | --edit-todo\n> ---\n> - Available options are\n> -v,verbose!         display a diffstat of what changed upstream\n> -q,quiet!           be quiet. implies --no-stat\n> -autostash          automatically stash/stash pop before and after\n> -fork-point         use 'merge-base --fork-point' to refine upstream\n> -onto=!             rebase onto given branch instead of upstream\n> -r,rebase-merges?   try to rebase merges instead of skipping them\n> -p,preserve-merges! try to recreate merges instead of ignoring them\n> -s,strategy=!       use the given merge strategy\n> -X,strategy-option=! pass the argument through to the merge strategy\n> -no-ff!             cherry-pick all commits, even if unchanged\n> -f,force-rebase!    cherry-pick all commits, even if unchanged\n> -m,merge!           use merging strategies to rebase\n> -i,interactive!     let the user edit the list of commits to rebase\n> -x,exec=!           add exec lines after each commit of the editable list\n> -k,keep-empty\t   preserve empty commits during rebase\n> -allow-empty-message allow rebasing commits with empty messages\n> -stat!              display a diffstat of what changed upstream\n> -n,no-stat!         do not show diffstat of what changed upstream\n> -verify             allow pre-rebase hook to run\n> -rerere-autoupdate  allow rerere to update index with resolved conflicts\n> -root!              rebase all reachable commits up to the root(s)\n> -autosquash         move commits that begin with squash!/fixup! under -i\n> -signoff            add a Signed-off-by: line to each commit\n> -committer-date-is-author-date! passed to 'git am'\n> -ignore-date!       passed to 'git am'\n> -whitespace=!       passed to 'git apply'\n> -ignore-whitespace! passed to 'git apply'\n> -C=!                passed to 'git apply'\n> -S,gpg-sign?        GPG-sign commits\n> - Actions:\n> -continue!          continue\n> -abort!             abort and check out the original branch\n> -skip!              skip current patch and continue\n> -edit-todo!         edit the todo list during an interactive rebase\n> -quit!              abort but keep HEAD where it is\n> -show-current-patch! show the patch file being applied or merged\n> -reschedule-failed-exec automatically reschedule failed exec commands\n> -\"\n> -. git-sh-setup\n> -set_reflog_action rebase\n> -require_work_tree_exists\n> -cd_to_toplevel\n> -\n> -LF='\n> -'\n> -ok_to_skip_pre_rebase=\n> -\n> -squash_onto=\n> -unset onto\n> -unset restrict_revision\n> -cmd=\n> -strategy=\n> -strategy_opts=\n> -do_merge=\n> -merge_dir=\"$GIT_DIR\"/rebase-merge\n> -apply_dir=\"$GIT_DIR\"/rebase-apply\n> -verbose=\n> -diffstat=\n> -test \"$(git config --bool rebase.stat)\" = true && diffstat=t\n> -autostash=\"$(git config --bool rebase.autostash || echo false)\"\n> -fork_point=auto\n> -git_am_opt=\n> -git_format_patch_opt=\n> -rebase_root=\n> -force_rebase=\n> -allow_rerere_autoupdate=\n> -# Non-empty if a rebase was in progress when 'git rebase' was invoked\n> -in_progress=\n> -# One of {am, merge, interactive}\n> -type=\n> -# One of {\"$GIT_DIR\"/rebase-apply, \"$GIT_DIR\"/rebase-merge}\n> -state_dir=\n> -# One of {'', continue, skip, abort}, as parsed from command line\n> -action=\n> -rebase_merges=\n> -rebase_cousins=\n> -preserve_merges=\n> -autosquash=\n> -keep_empty=\n> -allow_empty_message=--allow-empty-message\n> -signoff=\n> -reschedule_failed_exec=\n> -test \"$(git config --bool rebase.autosquash)\" = \"true\" && autosquash=t\n> -case \"$(git config --bool commit.gpgsign)\" in\n> -true)\tgpg_sign_opt=-S ;;\n> -*)\tgpg_sign_opt= ;;\n> -esac\n> -test \"$(git config --bool rebase.reschedulefailedexec)\" = \"true\" &&\n> -reschedule_failed_exec=--reschedule-failed-exec\n> -. git-rebase--common\n> -\n> -read_basic_state () {\n> -\ttest -f \"$state_dir/head-name\" &&\n> -\ttest -f \"$state_dir/onto\" &&\n> -\thead_name=$(cat \"$state_dir\"/head-name) &&\n> -\tonto=$(cat \"$state_dir\"/onto) &&\n> -\t# We always write to orig-head, but interactive rebase used to write to\n> -\t# head. Fall back to reading from head to cover for the case that the\n> -\t# user upgraded git with an ongoing interactive rebase.\n> -\tif test -f \"$state_dir\"/orig-head\n> -\tthen\n> -\t\torig_head=$(cat \"$state_dir\"/orig-head)\n> -\telse\n> -\t\torig_head=$(cat \"$state_dir\"/head)\n> -\tfi &&\n> -\ttest -f \"$state_dir\"/quiet && GIT_QUIET=t\n> -\ttest -f \"$state_dir\"/verbose && verbose=t\n> -\ttest -f \"$state_dir\"/strategy && strategy=\"$(cat \"$state_dir\"/strategy)\"\n> -\ttest -f \"$state_dir\"/strategy_opts &&\n> -\t\tstrategy_opts=\"$(cat \"$state_dir\"/strategy_opts)\"\n> -\ttest -f \"$state_dir\"/allow_rerere_autoupdate &&\n> -\t\tallow_rerere_autoupdate=\"$(cat \"$state_dir\"/allow_rerere_autoupdate)\"\n> -\ttest -f \"$state_dir\"/gpg_sign_opt &&\n> -\t\tgpg_sign_opt=\"$(cat \"$state_dir\"/gpg_sign_opt)\"\n> -\ttest -f \"$state_dir\"/signoff && {\n> -\t\tsignoff=\"$(cat \"$state_dir\"/signoff)\"\n> -\t\tforce_rebase=t\n> -\t}\n> -\ttest -f \"$state_dir\"/reschedule-failed-exec &&\n> -\t\treschedule_failed_exec=t\n> -}\n> -\n> -finish_rebase () {\n> -\trm -f \"$(git rev-parse --git-path REBASE_HEAD)\"\n> -\tapply_autostash &&\n> -\t{ git gc --auto || true; } &&\n> -\trm -rf \"$state_dir\"\n> -}\n> -\n> -run_interactive () {\n> -\tGIT_CHERRY_PICK_HELP=\"$resolvemsg\"\n> -\texport GIT_CHERRY_PICK_HELP\n> -\n> -\ttest -n \"$keep_empty\" && keep_empty=\"--keep-empty\"\n> -\ttest -n \"$rebase_merges\" && rebase_merges=\"--rebase-merges\"\n> -\ttest -n \"$rebase_cousins\" && rebase_cousins=\"--rebase-cousins\"\n> -\ttest -n \"$autosquash\" && autosquash=\"--autosquash\"\n> -\ttest -n \"$verbose\" && verbose=\"--verbose\"\n> -\ttest -n \"$force_rebase\" && force_rebase=\"--no-ff\"\n> -\ttest -n \"$restrict_revision\" && \\\n> -\t\trestrict_revision=\"--restrict-revision=^$restrict_revision\"\n> -\ttest -n \"$upstream\" && upstream=\"--upstream=$upstream\"\n> -\ttest -n \"$onto\" && onto=\"--onto=$onto\"\n> -\ttest -n \"$squash_onto\" && squash_onto=\"--squash-onto=$squash_onto\"\n> -\ttest -n \"$onto_name\" && onto_name=\"--onto-name=$onto_name\"\n> -\ttest -n \"$head_name\" && head_name=\"--head-name=$head_name\"\n> -\ttest -n \"$strategy\" && strategy=\"--strategy=$strategy\"\n> -\ttest -n \"$strategy_opts\" && strategy_opts=\"--strategy-opts=$strategy_opts\"\n> -\ttest -n \"$switch_to\" && switch_to=\"--switch-to=$switch_to\"\n> -\ttest -n \"$cmd\" && cmd=\"--cmd=$cmd\"\n> -\ttest -n \"$action\" && action=\"--$action\"\n> -\n> -\texec git rebase--interactive \"$action\" \"$keep_empty\" \"$rebase_merges\" \"$rebase_cousins\" \\\n> -\t\t\"$upstream\" \"$onto\" \"$squash_onto\" \"$restrict_revision\" \\\n> -\t\t\"$allow_empty_message\" \"$autosquash\" \"$verbose\" \\\n> -\t\t\"$force_rebase\" \"$onto_name\" \"$head_name\" \"$strategy\" \\\n> -\t\t\"$strategy_opts\" \"$cmd\" \"$switch_to\" \\\n> -\t\t\"$allow_rerere_autoupdate\" \"$gpg_sign_opt\" \"$signoff\" \\\n> -\t\t\"$reschedule_failed_exec\"\n> -}\n> -\n> -run_specific_rebase () {\n> -\tif [ \"$interactive_rebase\" = implied ]; then\n> -\t\tGIT_SEQUENCE_EDITOR=:\n> -\t\texport GIT_SEQUENCE_EDITOR\n> -\t\tautosquash=\n> -\tfi\n> -\n> -\tif test -n \"$interactive_rebase\" -a -z \"$preserve_merges\"\n> -\tthen\n> -\t\trun_interactive\n> -\telse\n> -\t\t. git-rebase--$type\n> -\n> -\t\tif test -z \"$preserve_merges\"\n> -\t\tthen\n> -\t\t\tgit_rebase__$type\n> -\t\telse\n> -\t\t\tgit_rebase__preserve_merges\n> -\t\tfi\n> -\tfi\n> -\n> -\tret=$?\n> -\tif test $ret -eq 0\n> -\tthen\n> -\t\tfinish_rebase\n> -\telif test $ret -eq 2 # special exit status for rebase -p\n> -\tthen\n> -\t\tapply_autostash &&\n> -\t\trm -rf \"$state_dir\" &&\n> -\t\tdie \"Nothing to do\"\n> -\tfi\n> -\texit $ret\n> -}\n> -\n> -run_pre_rebase_hook () {\n> -\tif test -z \"$ok_to_skip_pre_rebase\" &&\n> -\t   test -x \"$(git rev-parse --git-path hooks/pre-rebase)\"\n> -\tthen\n> -\t\t\"$(git rev-parse --git-path hooks/pre-rebase)\" ${1+\"$@\"} ||\n> -\t\tdie \"$(gettext \"The pre-rebase hook refused to rebase.\")\"\n> -\tfi\n> -}\n> -\n> -test -f \"$apply_dir\"/applying &&\n> -\tdie \"$(gettext \"It looks like 'git am' is in progress. Cannot rebase.\")\"\n> -\n> -if test -d \"$apply_dir\"\n> -then\n> -\ttype=am\n> -\tstate_dir=\"$apply_dir\"\n> -elif test -d \"$merge_dir\"\n> -then\n> -\ttype=interactive\n> -\tif test -d \"$merge_dir\"/rewritten\n> -\tthen\n> -\t\ttype=preserve-merges\n> -\t\tinteractive_rebase=explicit\n> -\t\tpreserve_merges=t\n> -\telif test -f \"$merge_dir\"/interactive\n> -\tthen\n> -\t\tinteractive_rebase=explicit\n> -\tfi\n> -\tstate_dir=\"$merge_dir\"\n> -fi\n> -test -n \"$type\" && in_progress=t\n> -\n> -total_argc=$#\n> -while test $# != 0\n> -do\n> -\tcase \"$1\" in\n> -\t--no-verify)\n> -\t\tok_to_skip_pre_rebase=yes\n> -\t\t;;\n> -\t--verify)\n> -\t\tok_to_skip_pre_rebase=\n> -\t\t;;\n> -\t--continue|--skip|--abort|--quit|--edit-todo|--show-current-patch)\n> -\t\ttest $total_argc -eq 2 || usage\n> -\t\taction=${1##--}\n> -\t\t;;\n> -\t--onto=*)\n> -\t\tonto=\"${1#--onto=}\"\n> -\t\t;;\n> -\t--exec=*)\n> -\t\tcmd=\"${cmd}exec ${1#--exec=}${LF}\"\n> -\t\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n> -\t\t;;\n> -\t--interactive)\n> -\t\tinteractive_rebase=explicit\n> -\t\t;;\n> -\t--keep-empty)\n> -\t\tkeep_empty=yes\n> -\t\t;;\n> -\t--allow-empty-message)\n> -\t\tallow_empty_message=--allow-empty-message\n> -\t\t;;\n> -\t--no-keep-empty)\n> -\t\tkeep_empty=\n> -\t\t;;\n> -\t--rebase-merges)\n> -\t\trebase_merges=t\n> -\t\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n> -\t\t;;\n> -\t--rebase-merges=*)\n> -\t\trebase_merges=t\n> -\t\tcase \"${1#*=}\" in\n> -\t\trebase-cousins) rebase_cousins=t;;\n> -\t\tno-rebase-cousins) rebase_cousins=;;\n> -\t\t*) die \"Unknown mode: $1\";;\n> -\t\tesac\n> -\t\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n> -\t\t;;\n> -\t--preserve-merges)\n> -\t\tpreserve_merges=t\n> -\t\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n> -\t\t;;\n> -\t--autosquash)\n> -\t\tautosquash=t\n> -\t\t;;\n> -\t--no-autosquash)\n> -\t\tautosquash=\n> -\t\t;;\n> -\t--fork-point)\n> -\t\tfork_point=t\n> -\t\t;;\n> -\t--no-fork-point)\n> -\t\tfork_point=\n> -\t\t;;\n> -\t--merge)\n> -\t\tdo_merge=t\n> -\t\t;;\n> -\t--strategy-option=*)\n> -\t\tstrategy_opts=\"$strategy_opts $(git rev-parse --sq-quote \"--${1#--strategy-option=}\" | sed -e s/^.//)\"\n> -\t\tdo_merge=t\n> -\t\ttest -z \"$strategy\" && strategy=recursive\n> -\t\t;;\n> -\t--strategy=*)\n> -\t\tstrategy=\"${1#--strategy=}\"\n> -\t\tdo_merge=t\n> -\t\t;;\n> -\t--no-stat)\n> -\t\tdiffstat=\n> -\t\t;;\n> -\t--stat)\n> -\t\tdiffstat=t\n> -\t\t;;\n> -\t--autostash)\n> -\t\tautostash=true\n> -\t\t;;\n> -\t--no-autostash)\n> -\t\tautostash=false\n> -\t\t;;\n> -\t--verbose)\n> -\t\tverbose=t\n> -\t\tdiffstat=t\n> -\t\tGIT_QUIET=\n> -\t\t;;\n> -\t--quiet)\n> -\t\tGIT_QUIET=t\n> -\t\tgit_am_opt=\"$git_am_opt -q\"\n> -\t\tverbose=\n> -\t\tdiffstat=\n> -\t\t;;\n> -\t--whitespace=*)\n> -\t\tgit_am_opt=\"$git_am_opt --whitespace=${1#--whitespace=}\"\n> -\t\tcase \"${1#--whitespace=}\" in\n> -\t\tfix|strip)\n> -\t\t\tforce_rebase=t\n> -\t\t\t;;\n> -\t\twarn|nowarn|error|error-all)\n> -\t\t\t;; # okay, known whitespace option\n> -\t\t*)\n> -\t\t\tdie \"fatal: Invalid whitespace option: '${1#*=}'\"\n> -\t\t\t;;\n> -\t\tesac\n> -\t\t;;\n> -\t--ignore-whitespace)\n> -\t\tgit_am_opt=\"$git_am_opt $1\"\n> -\t\t;;\n> -\t--signoff)\n> -\t\tsignoff=--signoff\n> -\t\t;;\n> -\t--no-signoff)\n> -\t\tsignoff=\n> -\t\t;;\n> -\t--committer-date-is-author-date|--ignore-date)\n> -\t\tgit_am_opt=\"$git_am_opt $1\"\n> -\t\tforce_rebase=t\n> -\t\t;;\n> -\t-C*[!0-9]*)\n> -\t\tdie \"fatal: switch \\`C' expects a numerical value\"\n> -\t\t;;\n> -\t-C*)\n> -\t\tgit_am_opt=\"$git_am_opt $1\"\n> -\t\t;;\n> -\t--root)\n> -\t\trebase_root=t\n> -\t\t;;\n> -\t--force-rebase|--no-ff)\n> -\t\tforce_rebase=t\n> -\t\t;;\n> -\t--rerere-autoupdate|--no-rerere-autoupdate)\n> -\t\tallow_rerere_autoupdate=\"$1\"\n> -\t\t;;\n> -\t--gpg-sign)\n> -\t\tgpg_sign_opt=-S\n> -\t\t;;\n> -\t--gpg-sign=*)\n> -\t\tgpg_sign_opt=\"-S${1#--gpg-sign=}\"\n> -\t\t;;\n> -\t--reschedule-failed-exec)\n> -\t\treschedule_failed_exec=--reschedule-failed-exec\n> -\t\t;;\n> -\t--no-reschedule-failed-exec)\n> -\t\treschedule_failed_exec=\n> -\t\t;;\n> -\t--)\n> -\t\tshift\n> -\t\tbreak\n> -\t\t;;\n> -\t*)\n> -\t\tusage\n> -\t\t;;\n> -\tesac\n> -\tshift\n> -done\n> -test $# -gt 2 && usage\n> -\n> -if test -n \"$action\"\n> -then\n> -\ttest -z \"$in_progress\" && die \"$(gettext \"No rebase in progress?\")\"\n> -\t# Only interactive rebase uses detailed reflog messages\n> -\tif test -n \"$interactive_rebase\" && test \"$GIT_REFLOG_ACTION\" = rebase\n> -\tthen\n> -\t\tGIT_REFLOG_ACTION=\"rebase -i ($action)\"\n> -\t\texport GIT_REFLOG_ACTION\n> -\tfi\n> -fi\n> -\n> -if test \"$action\" = \"edit-todo\" && test -z \"$interactive_rebase\"\n> -then\n> -\tdie \"$(gettext \"The --edit-todo action can only be used during interactive rebase.\")\"\n> -fi\n> -\n> -case \"$action\" in\n> -continue)\n> -\t# Sanity check\n> -\tgit rev-parse --verify HEAD >/dev/null ||\n> -\t\tdie \"$(gettext \"Cannot read HEAD\")\"\n> -\tgit update-index --ignore-submodules --refresh &&\n> -\tgit diff-files --quiet --ignore-submodules || {\n> -\t\techo \"$(gettext \"You must edit all merge conflicts and then\n> -mark them as resolved using git add\")\"\n> -\t\texit 1\n> -\t}\n> -\tread_basic_state\n> -\trun_specific_rebase\n> -\t;;\n> -skip)\n> -\toutput git reset --hard HEAD || exit $?\n> -\tread_basic_state\n> -\trun_specific_rebase\n> -\t;;\n> -abort)\n> -\tgit rerere clear\n> -\tread_basic_state\n> -\tcase \"$head_name\" in\n> -\trefs/*)\n> -\t\tgit symbolic-ref -m \"rebase: aborting\" HEAD $head_name ||\n> -\t\tdie \"$(eval_gettext \"Could not move back to \\$head_name\")\"\n> -\t\t;;\n> -\tesac\n> -\toutput git reset --hard $orig_head\n> -\tfinish_rebase\n> -\texit\n> -\t;;\n> -quit)\n> -\texec rm -rf \"$state_dir\"\n> -\t;;\n> -edit-todo)\n> -\trun_specific_rebase\n> -\t;;\n> -show-current-patch)\n> -\trun_specific_rebase\n> -\tdie \"BUG: run_specific_rebase is not supposed to return here\"\n> -\t;;\n> -esac\n> -\n> -# Make sure no rebase is in progress\n> -if test -n \"$in_progress\"\n> -then\n> -\tstate_dir_base=${state_dir##*/}\n> -\tcmd_live_rebase=\"git rebase (--continue | --abort | --skip)\"\n> -\tcmd_clear_stale_rebase=\"rm -fr \\\"$state_dir\\\"\"\n> -\tdie \"\n> -$(eval_gettext 'It seems that there is already a $state_dir_base directory, and\n> -I wonder if you are in the middle of another rebase.  If that is the\n> -case, please try\n> -\t$cmd_live_rebase\n> -If that is not the case, please\n> -\t$cmd_clear_stale_rebase\n> -and run me again.  I am stopping in case you still have something\n> -valuable there.')\"\n> -fi\n> -\n> -if test -n \"$rebase_root\" && test -z \"$onto\"\n> -then\n> -\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n> -fi\n> -\n> -if test -n \"$keep_empty\"\n> -then\n> -\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n> -fi\n> -\n> -actually_interactive=\n> -if test -n \"$interactive_rebase\"\n> -then\n> -\tif test -z \"$preserve_merges\"\n> -\tthen\n> -\t\ttype=interactive\n> -\telse\n> -\t\ttype=preserve-merges\n> -\tfi\n> -\tactually_interactive=t\n> -\tstate_dir=\"$merge_dir\"\n> -elif test -n \"$do_merge\"\n> -then\n> -\tinteractive_rebase=implied\n> -\ttype=interactive\n> -\tstate_dir=\"$merge_dir\"\n> -else\n> -\ttype=am\n> -\tstate_dir=\"$apply_dir\"\n> -fi\n> -\n> -if test -t 2 && test -z \"$GIT_QUIET\"\n> -then\n> -\tgit_format_patch_opt=\"$git_format_patch_opt --progress\"\n> -fi\n> -\n> -incompatible_opts=$(echo \" $git_am_opt \" | \\\n> -\t\t    sed -e 's/ -q / /g' -e 's/^ \\(.*\\) $/\\1/')\n> -if test -n \"$incompatible_opts\"\n> -then\n> -\tif test -n \"$actually_interactive\" || test \"$do_merge\"\n> -\tthen\n> -\t\tdie \"$(gettext \"fatal: cannot combine am options with either interactive or merge options\")\"\n> -\tfi\n> -fi\n> -\n> -if test -n \"$signoff\"\n> -then\n> -\ttest -n \"$preserve_merges\" &&\n> -\t\tdie \"$(gettext \"fatal: cannot combine '--signoff' with '--preserve-merges'\")\"\n> -\tgit_am_opt=\"$git_am_opt $signoff\"\n> -\tforce_rebase=t\n> -fi\n> -\n> -if test -n \"$preserve_merges\"\n> -then\n> -\t# Note: incompatibility with --signoff handled in signoff block above\n> -\t# Note: incompatibility with --interactive is just a strong warning;\n> -\t#       git-rebase.txt caveats with \"unless you know what you are doing\"\n> -\ttest -n \"$rebase_merges\" &&\n> -\t\tdie \"$(gettext \"fatal: cannot combine '--preserve-merges' with '--rebase-merges'\")\"\n> -\n> -\ttest -n \"$reschedule_failed_exec\" &&\n> -\t\tdie \"$(gettext \"error: cannot combine '--preserve-merges' with '--reschedule-failed-exec'\")\"\n> -fi\n> -\n> -if test -n \"$rebase_merges\"\n> -then\n> -\ttest -n \"$strategy_opts\" &&\n> -\t\tdie \"$(gettext \"fatal: cannot combine '--rebase-merges' with '--strategy-option'\")\"\n> -\ttest -n \"$strategy\" &&\n> -\t\tdie \"$(gettext \"fatal: cannot combine '--rebase-merges' with '--strategy'\")\"\n> -fi\n> -\n> -if test -z \"$rebase_root\"\n> -then\n> -\tcase \"$#\" in\n> -\t0)\n> -\t\tif ! upstream_name=$(git rev-parse --symbolic-full-name \\\n> -\t\t\t--verify -q @{upstream} 2>/dev/null)\n> -\t\tthen\n> -\t\t\t. git-parse-remote\n> -\t\t\terror_on_missing_default_upstream \"rebase\" \"rebase\" \\\n> -\t\t\t\t\"against\" \"git rebase $(gettext '<branch>')\"\n> -\t\tfi\n> -\n> -\t\ttest \"$fork_point\" = auto && fork_point=t\n> -\t\t;;\n> -\t*)\tupstream_name=\"$1\"\n> -\t\tif test \"$upstream_name\" = \"-\"\n> -\t\tthen\n> -\t\t\tupstream_name=\"@{-1}\"\n> -\t\tfi\n> -\t\tshift\n> -\t\t;;\n> -\tesac\n> -\tupstream=$(peel_committish \"${upstream_name}\") ||\n> -\tdie \"$(eval_gettext \"invalid upstream '\\$upstream_name'\")\"\n> -\tupstream_arg=\"$upstream_name\"\n> -else\n> -\tif test -z \"$onto\"\n> -\tthen\n> -\t\tempty_tree=$(git hash-object -t tree /dev/null)\n> -\t\tonto=$(git commit-tree $empty_tree </dev/null)\n> -\t\tsquash_onto=\"$onto\"\n> -\tfi\n> -\tunset upstream_name\n> -\tunset upstream\n> -\ttest $# -gt 1 && usage\n> -\tupstream_arg=--root\n> -fi\n> -\n> -# Make sure the branch to rebase onto is valid.\n> -onto_name=${onto-\"$upstream_name\"}\n> -case \"$onto_name\" in\n> -*...*)\n> -\tif\tleft=${onto_name%...*} right=${onto_name#*...} &&\n> -\t\tonto=$(git merge-base --all ${left:-HEAD} ${right:-HEAD})\n> -\tthen\n> -\t\tcase \"$onto\" in\n> -\t\t?*\"$LF\"?*)\n> -\t\t\tdie \"$(eval_gettext \"\\$onto_name: there are more than one merge bases\")\"\n> -\t\t\t;;\n> -\t\t'')\n> -\t\t\tdie \"$(eval_gettext \"\\$onto_name: there is no merge base\")\"\n> -\t\t\t;;\n> -\t\tesac\n> -\telse\n> -\t\tdie \"$(eval_gettext \"\\$onto_name: there is no merge base\")\"\n> -\tfi\n> -\t;;\n> -*)\n> -\tonto=$(peel_committish \"$onto_name\") ||\n> -\tdie \"$(eval_gettext \"Does not point to a valid commit: \\$onto_name\")\"\n> -\t;;\n> -esac\n> -\n> -# If the branch to rebase is given, that is the branch we will rebase\n> -# $branch_name -- branch/commit being rebased, or HEAD (already detached)\n> -# $orig_head -- commit object name of tip of the branch before rebasing\n> -# $head_name -- refs/heads/<that-branch> or \"detached HEAD\"\n> -switch_to=\n> -case \"$#\" in\n> -1)\n> -\t# Is it \"rebase other $branchname\" or \"rebase other $commit\"?\n> -\tbranch_name=\"$1\"\n> -\tswitch_to=\"$1\"\n> -\n> -\t# Is it a local branch?\n> -\tif git show-ref --verify --quiet -- \"refs/heads/$branch_name\" &&\n> -\t   orig_head=$(git rev-parse -q --verify \"refs/heads/$branch_name\")\n> -\tthen\n> -\t\thead_name=\"refs/heads/$branch_name\"\n> -\t# If not is it a valid ref (branch or commit)?\n> -\telif orig_head=$(git rev-parse -q --verify \"$branch_name\")\n> -\tthen\n> -\t\thead_name=\"detached HEAD\"\n> -\n> -\telse\n> -\t\tdie \"$(eval_gettext \"fatal: no such branch/commit '\\$branch_name'\")\"\n> -\tfi\n> -\t;;\n> -0)\n> -\t# Do not need to switch branches, we are already on it.\n> -\tif branch_name=$(git symbolic-ref -q HEAD)\n> -\tthen\n> -\t\thead_name=$branch_name\n> -\t\tbranch_name=$(expr \"z$branch_name\" : 'zrefs/heads/\\(.*\\)')\n> -\telse\n> -\t\thead_name=\"detached HEAD\"\n> -\t\tbranch_name=HEAD\n> -\tfi\n> -\torig_head=$(git rev-parse --verify HEAD) || exit\n> -\t;;\n> -*)\n> -\tdie \"BUG: unexpected number of arguments left to parse\"\n> -\t;;\n> -esac\n> -\n> -if test \"$fork_point\" = t\n> -then\n> -\tnew_upstream=$(git merge-base --fork-point \"$upstream_name\" \\\n> -\t\t\t\"${switch_to:-HEAD}\")\n> -\tif test -n \"$new_upstream\"\n> -\tthen\n> -\t\trestrict_revision=$new_upstream\n> -\tfi\n> -fi\n> -\n> -if test \"$autostash\" = true && ! (require_clean_work_tree) 2>/dev/null\n> -then\n> -\tstash_sha1=$(git stash create \"autostash\") ||\n> -\tdie \"$(gettext 'Cannot autostash')\"\n> -\n> -\tmkdir -p \"$state_dir\" &&\n> -\techo $stash_sha1 >\"$state_dir/autostash\" &&\n> -\tstash_abbrev=$(git rev-parse --short $stash_sha1) &&\n> -\techo \"$(eval_gettext 'Created autostash: $stash_abbrev')\" &&\n> -\tgit reset --hard\n> -fi\n> -\n> -require_clean_work_tree \"rebase\" \"$(gettext \"Please commit or stash them.\")\"\n> -\n> -# Now we are rebasing commits $upstream..$orig_head (or with --root,\n> -# everything leading up to $orig_head) on top of $onto\n> -\n> -# Check if we are already based on $onto with linear history,\n> -# but this should be done only when upstream and onto are the same\n> -# and if this is not an interactive rebase.\n> -mb=$(git merge-base \"$onto\" \"$orig_head\")\n> -if test -z \"$actually_interactive\" && test \"$upstream\" = \"$onto\" &&\n> -\ttest \"$mb\" = \"$onto\" && test -z \"$restrict_revision\" &&\n> -\t# linear history?\n> -\t! (git rev-list --parents \"$onto\"..\"$orig_head\" | sane_grep \" .* \") > /dev/null\n> -then\n> -\tif test -z \"$force_rebase\"\n> -\tthen\n> -\t\t# Lazily switch to the target branch if needed...\n> -\t\ttest -z \"$switch_to\" ||\n> -\t\tGIT_REFLOG_ACTION=\"$GIT_REFLOG_ACTION: checkout $switch_to\" \\\n> -\t\t\tgit checkout -q \"$switch_to\" --\n> -\t\tif test \"$branch_name\" = \"HEAD\" &&\n> -\t\t\t ! git symbolic-ref -q HEAD\n> -\t\tthen\n> -\t\t\tsay \"$(eval_gettext \"HEAD is up to date.\")\"\n> -\t\telse\n> -\t\t\tsay \"$(eval_gettext \"Current branch \\$branch_name is up to date.\")\"\n> -\t\tfi\n> -\t\tfinish_rebase\n> -\t\texit 0\n> -\telse\n> -\t\tif test \"$branch_name\" = \"HEAD\" &&\n> -\t\t\t ! git symbolic-ref -q HEAD\n> -\t\tthen\n> -\t\t\tsay \"$(eval_gettext \"HEAD is up to date, rebase forced.\")\"\n> -\t\telse\n> -\t\t\tsay \"$(eval_gettext \"Current branch \\$branch_name is up to date, rebase forced.\")\"\n> -\t\tfi\n> -\tfi\n> -fi\n> -\n> -# If a hook exists, give it a chance to interrupt\n> -run_pre_rebase_hook \"$upstream_arg\" \"$@\"\n> -\n> -if test -n \"$diffstat\"\n> -then\n> -\tif test -n \"$verbose\"\n> -\tthen\n> -\t\tif test -z \"$mb\"\n> -\t\tthen\n> -\t\t\techo \"$(eval_gettext \"Changes to \\$onto:\")\"\n> -\t\telse\n> -\t\t\techo \"$(eval_gettext \"Changes from \\$mb to \\$onto:\")\"\n> -\t\tfi\n> -\tfi\n> -\tmb_tree=\"${mb:-$(git hash-object -t tree /dev/null)}\"\n> -\t# We want color (if set), but no pager\n> -\tGIT_PAGER='' git diff --stat --summary \"$mb_tree\" \"$onto\"\n> -fi\n> -\n> -if test -z \"$actually_interactive\" && test \"$mb\" = \"$orig_head\"\n> -then\n> -\tsay \"$(eval_gettext \"Fast-forwarded \\$branch_name to \\$onto_name.\")\"\n> -\tGIT_REFLOG_ACTION=\"$GIT_REFLOG_ACTION: checkout $onto_name\" \\\n> -\t\tgit checkout -q \"$onto^0\" || die \"could not detach HEAD\"\n> -\t# If the $onto is a proper descendant of the tip of the branch, then\n> -\t# we just fast-forwarded.\n> -\tgit update-ref ORIG_HEAD $orig_head\n> -\tmove_to_original_branch\n> -\tfinish_rebase\n> -\texit 0\n> -fi\n> -\n> -test -n \"$interactive_rebase\" && run_specific_rebase\n> -\n> -# Detach HEAD and reset the tree\n> -say \"$(gettext \"First, rewinding head to replay your work on top of it...\")\"\n> -\n> -GIT_REFLOG_ACTION=\"$GIT_REFLOG_ACTION: checkout $onto_name\" \\\n> -\tgit checkout -q \"$onto^0\" || die \"could not detach HEAD\"\n> -git update-ref ORIG_HEAD $orig_head\n> -\n> -if test -n \"$rebase_root\"\n> -then\n> -\trevisions=\"$onto..$orig_head\"\n> -else\n> -\trevisions=\"${restrict_revision-$upstream}..$orig_head\"\n> -fi\n> -\n> -run_specific_rebase\n> diff --git a/t/README b/t/README\n> index 7a3d582267c..385262357b5 100644\n> --- a/t/README\n> +++ b/t/README\n> @@ -379,10 +379,6 @@ the --no-sparse command-line argument.\n>   GIT_TEST_PRELOAD_INDEX=<boolean> exercises the preload-index code path\n>   by overriding the minimum number of cache entries required per thread.\n>   \n> -GIT_TEST_REBASE_USE_BUILTIN=<boolean>, when false, disables the\n> -builtin version of git-rebase. See 'rebase.useBuiltin' in\n> -git-config(1).\n> -\n>   GIT_TEST_INDEX_THREADS=<n> enables exercising the multi-threaded loading\n>   of the index for the whole test suite by bypassing the default number of\n>   cache entries and thread minimums. Setting this to 1 will make the\n> diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh\n> index 3e73f7584ce..a809de93047 100755\n> --- a/t/t3400-rebase.sh\n> +++ b/t/t3400-rebase.sh\n> @@ -311,4 +311,20 @@ test_expect_success 'rebase--merge.sh and --show-current-patch' '\n>   \t)\n>   '\n>   \n> +test_expect_success 'rebase -c rebase.useBuiltin=false warning' '\n> +\texpected=\"rebase.useBuiltin support has been removed\" &&\n> +\n> +\t# Only warn when the legacy rebase is requested...\n> +\ttest_must_fail git -c rebase.useBuiltin=false rebase 2>err &&\n> +\ttest_i18ngrep \"$expected\" err &&\n> +\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=false git rebase 2>err &&\n> +\ttest_i18ngrep \"$expected\" err &&\n> +\n> +\t# ...not when we would have used the built-in anyway\n> +\ttest_must_fail git -c rebase.useBuiltin=true rebase 2>err &&\n> +\ttest_must_be_empty err &&\n> +\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=true git rebase 2>err &&\n> +\ttest_must_be_empty err\n> +'\n> +\n>   test_done\n> diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\n> index b60b11f9f2f..1723e1a8585 100755\n> --- a/t/t3404-rebase-interactive.sh\n> +++ b/t/t3404-rebase-interactive.sh\n> @@ -149,12 +149,10 @@ test_expect_success 'rebase -i with the exec command checks tree cleanness' '\n>   \n>   test_expect_success 'rebase -x with empty command fails' '\n>   \ttest_when_finished \"git rebase --abort ||:\" &&\n> -\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=true \\\n> -\t\tgit rebase -x \"\" @ 2>actual &&\n> +\ttest_must_fail env git rebase -x \"\" @ 2>actual &&\n>   \ttest_write_lines \"error: empty exec command\" >expected &&\n>   \ttest_i18ncmp expected actual &&\n> -\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=true \\\n> -\t\tgit rebase -x \" \" @ 2>actual &&\n> +\ttest_must_fail env git rebase -x \" \" @ 2>actual &&\n>   \ttest_i18ncmp expected actual\n>   '\n>   \n> @@ -162,8 +160,7 @@ LF='\n>   '\n>   test_expect_success 'rebase -x with newline in command fails' '\n>   \ttest_when_finished \"git rebase --abort ||:\" &&\n> -\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=true \\\n> -\t\tgit rebase -x \"a${LF}b\" @ 2>actual &&\n> +\ttest_must_fail env git rebase -x \"a${LF}b\" @ 2>actual &&\n>   \ttest_write_lines \"error: exec commands cannot contain newlines\" \\\n>   \t\t\t >expected &&\n>   \ttest_i18ncmp expected actual\n> \n"},{"id":"420039","messageId":"patch-1.1-df026b00b67-20210323T152302Z-avarab@gmail.com","threadId":"50341","inReplyTo":"20190318110152.27246-1-avarab@gmail.com","subject":"[PATCH] rebase: remove transitory rebase.useBuiltin setting & env","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-03-23T15:23:58Z","receivedAt":"2021-03-23T15:25:15Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Remove the rebase.useBuiltin setting and the now-obsolete\nGIT_TEST_REBASE_USE_BUILTIN test flag.\n\nThis was left in place after my d03ebd411c6 (rebase: remove the\nrebase.useBuiltin setting, 2019-03-18) to help anyone who'd used the\nexperimental flag and wanted to know that it was the default, or that\nthey should transition their test environment to use the builtin\nrebase unconditionally.\n\nIt's been more than long enough for those users to get a headsup about\nthis. So remove all the scaffolding that was left inplace after\nd03ebd411c6. I'm also removing the documentation entry, if anyone\nstill has this left in their configuration they can do some source\narchaeology to figure out what it used to do, which makes more sense\nthan exposing every git user reading the documentation to this legacy\nconfiguration switch.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n Documentation/config/rebase.txt |  7 -------\n builtin/rebase.c                | 11 -----------\n t/t3400-rebase.sh               | 16 ----------------\n 3 files changed, 34 deletions(-)\n\ndiff --git a/Documentation/config/rebase.txt b/Documentation/config/rebase.txt\nindex 214f31b451f..8c979cb20f2 100644\n--- a/Documentation/config/rebase.txt\n+++ b/Documentation/config/rebase.txt\n@@ -1,10 +1,3 @@\n-rebase.useBuiltin::\n-\tUnused configuration variable. Used in Git versions 2.20 and\n-\t2.21 as an escape hatch to enable the legacy shellscript\n-\timplementation of rebase. Now the built-in rewrite of it in C\n-\tis always used. Setting this will emit a warning, to alert any\n-\tremaining users that setting this now does nothing.\n-\n rebase.backend::\n \tDefault backend to use for rebasing.  Possible choices are\n \t'apply' or 'merge'.  In the future, if the merge backend gains\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex de400f9a197..783b526f6e7 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -100,7 +100,6 @@ struct rebase_options {\n \tchar *strategy, *strategy_opts;\n \tstruct strbuf git_format_patch_opt;\n \tint reschedule_failed_exec;\n-\tint use_legacy_rebase;\n \tint reapply_cherry_picks;\n \tint fork_point;\n };\n@@ -1102,11 +1101,6 @@ static int rebase_config(const char *var, const char *value, void *data)\n \t\treturn 0;\n \t}\n \n-\tif (!strcmp(var, \"rebase.usebuiltin\")) {\n-\t\topts->use_legacy_rebase = !git_config_bool(var, value);\n-\t\treturn 0;\n-\t}\n-\n \tif (!strcmp(var, \"rebase.backend\")) {\n \t\treturn git_config_string(&opts->default_backend, var, value);\n \t}\n@@ -1441,11 +1435,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \tgpg_sign = options.gpg_sign_opt ? \"\" : NULL;\n \tFREE_AND_NULL(options.gpg_sign_opt);\n \n-\tif (options.use_legacy_rebase ||\n-\t    !git_env_bool(\"GIT_TEST_REBASE_USE_BUILTIN\", -1))\n-\t\twarning(_(\"the rebase.useBuiltin support has been removed!\\n\"\n-\t\t\t  \"See its entry in 'git help config' for details.\"));\n-\n \tstrbuf_reset(&buf);\n \tstrbuf_addf(&buf, \"%s/applying\", apply_dir());\n \tif(file_exists(buf.buf))\ndiff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh\nindex 587b408063a..0bb88aa982b 100755\n--- a/t/t3400-rebase.sh\n+++ b/t/t3400-rebase.sh\n@@ -388,22 +388,6 @@ test_expect_success 'rebase--merge.sh and --show-current-patch' '\n \t)\n '\n \n-test_expect_success 'rebase -c rebase.useBuiltin=false warning' '\n-\texpected=\"rebase.useBuiltin support has been removed\" &&\n-\n-\t# Only warn when the legacy rebase is requested...\n-\ttest_must_fail git -c rebase.useBuiltin=false rebase 2>err &&\n-\ttest_i18ngrep \"$expected\" err &&\n-\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=false git rebase 2>err &&\n-\ttest_i18ngrep \"$expected\" err &&\n-\n-\t# ...not when we would have used the built-in anyway\n-\ttest_must_fail git -c rebase.useBuiltin=true rebase 2>err &&\n-\ttest_must_be_empty err &&\n-\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=true git rebase 2>err &&\n-\ttest_must_be_empty err\n-'\n-\n test_expect_success 'switch to branch checked out here' '\n \tgit checkout main &&\n \tgit rebase main main\n-- \n2.31.0.366.g75c23356abd\n\n"},{"id":"420062","messageId":"xmqqv99h1u1k.fsf@gitster.g","threadId":"50341","inReplyTo":"patch-1.1-df026b00b67-20210323T152302Z-avarab@gmail.com","subject":"Re: [PATCH] rebase: remove transitory rebase.useBuiltin setting & env","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2021-03-23T20:42:15Z","receivedAt":"2021-03-23T20:43:12Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:\n\n> It's been more than long enough for those users to get a headsup about\n> this. So remove all the scaffolding that was left inplace after\n> d03ebd411c6. I'm also removing the documentation entry, if anyone\n> still has this left in their configuration they can do some source\n> archaeology to figure out what it used to do, which makes more sense\n> than exposing every git user reading the documentation to this legacy\n> configuration switch.\n\nOK, this concludes the long journey of replacing the scripted \"git\nrebase\" with its reimplementation in C by removing the last trace\nof the former.\n\nIt would be nice to have Acks from those involved in the\nreimplementation effort, to celebrate the occasion.\n\n> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n> ---\n>  Documentation/config/rebase.txt |  7 -------\n>  builtin/rebase.c                | 11 -----------\n>  t/t3400-rebase.sh               | 16 ----------------\n>  3 files changed, 34 deletions(-)\n>\n> diff --git a/Documentation/config/rebase.txt b/Documentation/config/rebase.txt\n> index 214f31b451f..8c979cb20f2 100644\n> --- a/Documentation/config/rebase.txt\n> +++ b/Documentation/config/rebase.txt\n> @@ -1,10 +1,3 @@\n> -rebase.useBuiltin::\n> -\tUnused configuration variable. Used in Git versions 2.20 and\n> -\t2.21 as an escape hatch to enable the legacy shellscript\n> -\timplementation of rebase. Now the built-in rewrite of it in C\n> -\tis always used. Setting this will emit a warning, to alert any\n> -\tremaining users that setting this now does nothing.\n> -\n"},{"id":"420068","messageId":"nycvar.QRO.7.76.6.2103232152090.50@tvgsbejvaqbjf.bet","threadId":"50341","inReplyTo":"patch-1.1-df026b00b67-20210323T152302Z-avarab@gmail.com","subject":"Re: [PATCH] rebase: remove transitory rebase.useBuiltin setting & env","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2021-03-23T20:52:22Z","receivedAt":"2021-03-23T20:53:11Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Ævar,\n\nOn Tue, 23 Mar 2021, Ævar Arnfjörð Bjarmason wrote:\n\n> Remove the rebase.useBuiltin setting and the now-obsolete\n> GIT_TEST_REBASE_USE_BUILTIN test flag.\n>\n> This was left in place after my d03ebd411c6 (rebase: remove the\n> rebase.useBuiltin setting, 2019-03-18) to help anyone who'd used the\n> experimental flag and wanted to know that it was the default, or that\n> they should transition their test environment to use the builtin\n> rebase unconditionally.\n>\n> It's been more than long enough for those users to get a headsup about\n> this. So remove all the scaffolding that was left inplace after\n> d03ebd411c6. I'm also removing the documentation entry, if anyone\n> still has this left in their configuration they can do some source\n> archaeology to figure out what it used to do, which makes more sense\n> than exposing every git user reading the documentation to this legacy\n> configuration switch.\n>\n> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n\nACK!\nDscho\n\n> ---\n>  Documentation/config/rebase.txt |  7 -------\n>  builtin/rebase.c                | 11 -----------\n>  t/t3400-rebase.sh               | 16 ----------------\n>  3 files changed, 34 deletions(-)\n>\n> diff --git a/Documentation/config/rebase.txt b/Documentation/config/rebase.txt\n> index 214f31b451f..8c979cb20f2 100644\n> --- a/Documentation/config/rebase.txt\n> +++ b/Documentation/config/rebase.txt\n> @@ -1,10 +1,3 @@\n> -rebase.useBuiltin::\n> -\tUnused configuration variable. Used in Git versions 2.20 and\n> -\t2.21 as an escape hatch to enable the legacy shellscript\n> -\timplementation of rebase. Now the built-in rewrite of it in C\n> -\tis always used. Setting this will emit a warning, to alert any\n> -\tremaining users that setting this now does nothing.\n> -\n>  rebase.backend::\n>  \tDefault backend to use for rebasing.  Possible choices are\n>  \t'apply' or 'merge'.  In the future, if the merge backend gains\n> diff --git a/builtin/rebase.c b/builtin/rebase.c\n> index de400f9a197..783b526f6e7 100644\n> --- a/builtin/rebase.c\n> +++ b/builtin/rebase.c\n> @@ -100,7 +100,6 @@ struct rebase_options {\n>  \tchar *strategy, *strategy_opts;\n>  \tstruct strbuf git_format_patch_opt;\n>  \tint reschedule_failed_exec;\n> -\tint use_legacy_rebase;\n>  \tint reapply_cherry_picks;\n>  \tint fork_point;\n>  };\n> @@ -1102,11 +1101,6 @@ static int rebase_config(const char *var, const char *value, void *data)\n>  \t\treturn 0;\n>  \t}\n>\n> -\tif (!strcmp(var, \"rebase.usebuiltin\")) {\n> -\t\topts->use_legacy_rebase = !git_config_bool(var, value);\n> -\t\treturn 0;\n> -\t}\n> -\n>  \tif (!strcmp(var, \"rebase.backend\")) {\n>  \t\treturn git_config_string(&opts->default_backend, var, value);\n>  \t}\n> @@ -1441,11 +1435,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>  \tgpg_sign = options.gpg_sign_opt ? \"\" : NULL;\n>  \tFREE_AND_NULL(options.gpg_sign_opt);\n>\n> -\tif (options.use_legacy_rebase ||\n> -\t    !git_env_bool(\"GIT_TEST_REBASE_USE_BUILTIN\", -1))\n> -\t\twarning(_(\"the rebase.useBuiltin support has been removed!\\n\"\n> -\t\t\t  \"See its entry in 'git help config' for details.\"));\n> -\n>  \tstrbuf_reset(&buf);\n>  \tstrbuf_addf(&buf, \"%s/applying\", apply_dir());\n>  \tif(file_exists(buf.buf))\n> diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh\n> index 587b408063a..0bb88aa982b 100755\n> --- a/t/t3400-rebase.sh\n> +++ b/t/t3400-rebase.sh\n> @@ -388,22 +388,6 @@ test_expect_success 'rebase--merge.sh and --show-current-patch' '\n>  \t)\n>  '\n>\n> -test_expect_success 'rebase -c rebase.useBuiltin=false warning' '\n> -\texpected=\"rebase.useBuiltin support has been removed\" &&\n> -\n> -\t# Only warn when the legacy rebase is requested...\n> -\ttest_must_fail git -c rebase.useBuiltin=false rebase 2>err &&\n> -\ttest_i18ngrep \"$expected\" err &&\n> -\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=false git rebase 2>err &&\n> -\ttest_i18ngrep \"$expected\" err &&\n> -\n> -\t# ...not when we would have used the built-in anyway\n> -\ttest_must_fail git -c rebase.useBuiltin=true rebase 2>err &&\n> -\ttest_must_be_empty err &&\n> -\ttest_must_fail env GIT_TEST_REBASE_USE_BUILTIN=true git rebase 2>err &&\n> -\ttest_must_be_empty err\n> -'\n> -\n>  test_expect_success 'switch to branch checked out here' '\n>  \tgit checkout main &&\n>  \tgit rebase main main\n> --\n> 2.31.0.366.g75c23356abd\n>\n>\n"}]}