{"thread":{"id":"52758","subject":"[BUG?] 'git rebase --abort' couldn't abort aborted rebase","startedAt":"2020-02-07T11:10:19Z","lastAt":"2020-02-07T17:53:05Z","messageCount":4,"participants":["SZEDER Gábor","Elijah Newren"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"391318","messageId":"20200207111008.GA2868@szeder.dev","threadId":"52758","inReplyTo":null,"subject":"[BUG?] 'git rebase --abort' couldn't abort aborted rebase","fromName":"SZEDER Gábor","fromEmail":"szeder.dev@gmail.com","sentAt":"2020-02-07T11:10:08Z","receivedAt":"2020-02-07T11:10:19Z","isPatch":false,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"That's a good subject, isn't it? :)\n\nSo, to clarify: apparently it is possible to abort an ongoing 'git\nrebase' process with ctrl-C in just the right moment that a subsequent\n'git rebase --abort' will refuse to clear it up.\n\nI somehow messed up the upstream and branch parameters of 'git\nrebase', and ended up trying to rebase a fairly recent (post v2.24.0)\nbranch on top of v2.22.0.  Upon seeing the unexpectedly large number\nof patches I realized that something is wrong, hit ctrl-C right away,\nand this is what happened:\n\n  $ git rebase v2.22.0 <a-branch-on-top-of-2.24.0>\n  First, rewinding head to replay your work on top of it...\n  Generating patches: 100% (1108/1108), done.\n  Applying: send-email: move the read_config() function above getopts\n  Applying: send-email: rename the @bcclist variable for consistency\n  Applying: send-email: do defaults -> config -> getopt in that order\n  Using index info to reconstruct a base tree...\n  M       git-send-email.perl\n  M       t/t9001-send-email.sh\n  Falling back to patching base and 3-way merge...\n  Auto-merging t/t9001-send-email.sh\n  Auto-merging git-send-email.perl\n  ^C\n  ((5f07da12ac...) *|REBASE 3/1108)$ git rebase --abort \n  error: could not read '/home/szeder/src/git/.git/worktrees/WT/rebase-apply/head-name': No such file or directory\n   \n\"Fortunately\" it was in a separate worktree, so I could easily get out\nof the situation by forcibly deleting that worktree.  Unfortunately,\nthat was exactly what I did, instead of securing the failed state for\nlater analysis...  sorry.\nThe only thing I still have is the list of files in the rebase directory,\nrescued from the terminal's scrollback buffer:\n\n  $ ls ~/src/git/.git/worktrees/WT/rebase-apply/\n  < ... omitting the 1k+ patch files ... >\n  abort-safety\n  apply-opt\n  author-script\n  final-commit\n  keep\n  last\n  messageid\n  next\n  original-commit\n  patch\n  patch-merge-index\n  quiet\n  rebasing\n  rewritten\n  scissors\n  sign\n  threeway\n  utf8\n\nAll this is with a git built from current 'next', with a bunch of\nunrelated (none of them touches rebase or the sequencer) patches on\ntop.\n\n\n"},{"id":"391320","messageId":"20200207114954.GB2868@szeder.dev","threadId":"52758","inReplyTo":"20200207111008.GA2868@szeder.dev","subject":"Re: [BUG?] 'git rebase --abort' couldn't abort aborted rebase","fromName":"SZEDER Gábor","fromEmail":"szeder.dev@gmail.com","sentAt":"2020-02-07T11:49:54Z","receivedAt":"2020-02-07T11:50:02Z","isPatch":false,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"On Fri, Feb 07, 2020 at 12:10:08PM +0100, SZEDER Gábor wrote:\n> That's a good subject, isn't it? :)\n> \n> So, to clarify: apparently it is possible to abort an ongoing 'git\n> rebase' process with ctrl-C in just the right moment that a subsequent\n> 'git rebase --abort' will refuse to clear it up.\n> \n> I somehow messed up the upstream and branch parameters of 'git\n> rebase', and ended up trying to rebase a fairly recent (post v2.24.0)\n> branch on top of v2.22.0.  Upon seeing the unexpectedly large number\n> of patches I realized that something is wrong, hit ctrl-C right away,\n> and this is what happened:\n> \n>   $ git rebase v2.22.0 <a-branch-on-top-of-2.24.0>\n>   First, rewinding head to replay your work on top of it...\n>   Generating patches: 100% (1108/1108), done.\n>   Applying: send-email: move the read_config() function above getopts\n>   Applying: send-email: rename the @bcclist variable for consistency\n>   Applying: send-email: do defaults -> config -> getopt in that order\n>   Using index info to reconstruct a base tree...\n>   M       git-send-email.perl\n>   M       t/t9001-send-email.sh\n>   Falling back to patching base and 3-way merge...\n>   Auto-merging t/t9001-send-email.sh\n>   Auto-merging git-send-email.perl\n>   ^C\n>   ((5f07da12ac...) *|REBASE 3/1108)$ git rebase --abort \n>   error: could not read '/home/szeder/src/git/.git/worktrees/WT/rebase-apply/head-name': No such file or directory\n>    \n> \"Fortunately\" it was in a separate worktree, so I could easily get out\n> of the situation by forcibly deleting that worktree.  Unfortunately,\n> that was exactly what I did, instead of securing the failed state for\n> later analysis...  sorry.\n\n> All this is with a git built from current 'next', with a bunch of\n> unrelated (none of them touches rebase or the sequencer) patches on\n> top.\n\nTrying to reproduce it is a hit or miss... well, mostly miss :)\n\nThere is a rather short window when 'git rebase' applies patches\nbefore hitting a first merge conflict.  If the ctrl-C arrives before\n'git rebase' starts applying patches, then it cleans everything up,\nand we are not rebasing, so there is no need for 'git rebase --abort'.\nOnce 'git rebase' stops because of the merge conflict we get our shell\nback, and 'git rebase --abort' works as it should.  But after a good\ncouple of tries I managed to hit ctrl-C while 'git rebase' was\napplying patches:\n\n  $ ./BUILDS/v2.25.0/bin/git rebase v2.22.0 v2.24.0^{commit}\n  First, rewinding head to replay your work on top of it...\n  Generating patches: 100% (1049/1049), done.\n  Applying: send-email: move the read_config() function above getopts\n  ^C\n  ((v2.22.0) +|REBASE 1/1049)$ ./BUILDS/v2.25.0/bin/git rebase --abort\n  error: could not read '.git/rebase-apply/head-name': No such file or directory\n\nNote that I'm using v2.25.0 here, so the problem is not with 'next' or\nwith my patches.  Also note that I reproduced the error in the main\nworktree, and only using commits that are present in git.git.\n\n\nFinally, note the 'v2.24.0^{commit}' parameter, in particular the\n'^{commit}' part.  That's important, because without it we stumble\nupon _another_ bug:\n\n  $ git rebase v2.22.0 v2.24.0\n  error: Object 1cc4bc0fcd93f816d514d77c29f2cc9ffdd8ae09 not a commit\n  First, rewinding head to replay your work on top of it...\n  Generating patches: 100% (1049/1049), done.\n  Applying: send-email: move the read_config() function above getopts\n  < ... applying further patches and hitting a merge conflict ... >\n  Resolve all conflicts manually, mark them as resolved with\n  \"git add/rm <conflicted_files>\", then run \"git rebase --continue\".\n  You can instead skip this commit: run \"git rebase --skip\".\n  To abort and get back to the state before \"git rebase\", run \"git rebase --abort\".\n  (detached HEAD *+|REBASE 7/1049)$ git rebase --abort \n  error: update_ref failed for ref 'HEAD': cannot update ref 'HEAD': trying to write non-commit object 1cc4bc0fcd93f816d514d77c29f2cc9ffdd8ae09 to branch 'HEAD'\n\nSo 'git rebase' shows an error right at the beginning when rebasing a\ntag, but then continues anyway.  However, 'git rebase --abort' can't\nrestore the original state.\n\n"},{"id":"391322","messageId":"20200207132152.GC2868@szeder.dev","threadId":"52758","inReplyTo":"20200207114954.GB2868@szeder.dev","subject":"Re: [BUG?] 'git rebase --abort' couldn't abort aborted rebase","fromName":"SZEDER Gábor","fromEmail":"szeder.dev@gmail.com","sentAt":"2020-02-07T13:21:52Z","receivedAt":"2020-02-07T13:22:02Z","isPatch":false,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"On Fri, Feb 07, 2020 at 12:49:54PM +0100, SZEDER Gábor wrote:\n> On Fri, Feb 07, 2020 at 12:10:08PM +0100, SZEDER Gábor wrote:\n> > That's a good subject, isn't it? :)\n> > \n> > So, to clarify: apparently it is possible to abort an ongoing 'git\n> > rebase' process with ctrl-C in just the right moment that a subsequent\n> > 'git rebase --abort' will refuse to clear it up.\n> > \n> > I somehow messed up the upstream and branch parameters of 'git\n> > rebase', and ended up trying to rebase a fairly recent (post v2.24.0)\n> > branch on top of v2.22.0.  Upon seeing the unexpectedly large number\n> > of patches I realized that something is wrong, hit ctrl-C right away,\n> > and this is what happened:\n> > \n> >   $ git rebase v2.22.0 <a-branch-on-top-of-2.24.0>\n> >   First, rewinding head to replay your work on top of it...\n> >   Generating patches: 100% (1108/1108), done.\n> >   Applying: send-email: move the read_config() function above getopts\n> >   Applying: send-email: rename the @bcclist variable for consistency\n> >   Applying: send-email: do defaults -> config -> getopt in that order\n> >   Using index info to reconstruct a base tree...\n> >   M       git-send-email.perl\n> >   M       t/t9001-send-email.sh\n> >   Falling back to patching base and 3-way merge...\n> >   Auto-merging t/t9001-send-email.sh\n> >   Auto-merging git-send-email.perl\n> >   ^C\n> >   ((5f07da12ac...) *|REBASE 3/1108)$ git rebase --abort \n> >   error: could not read '/home/szeder/src/git/.git/worktrees/WT/rebase-apply/head-name': No such file or directory\n> >    \n> > \"Fortunately\" it was in a separate worktree, so I could easily get out\n> > of the situation by forcibly deleting that worktree.  Unfortunately,\n> > that was exactly what I did, instead of securing the failed state for\n> > later analysis...  sorry.\n> \n> > All this is with a git built from current 'next', with a bunch of\n> > unrelated (none of them touches rebase or the sequencer) patches on\n> > top.\n> \n> Trying to reproduce it is a hit or miss... well, mostly miss :)\n> \n> There is a rather short window when 'git rebase' applies patches\n> before hitting a first merge conflict.  If the ctrl-C arrives before\n> 'git rebase' starts applying patches, then it cleans everything up,\n> and we are not rebasing, so there is no need for 'git rebase --abort'.\n> Once 'git rebase' stops because of the merge conflict we get our shell\n> back, and 'git rebase --abort' works as it should.  But after a good\n> couple of tries I managed to hit ctrl-C while 'git rebase' was\n> applying patches:\n\nThis patch below increases the size of the window where a ctrl-C gets\nus into that problematic situation:\n\ndiff --git a/builtin/am.c b/builtin/am.c\nindex 8181c2aef3..5d62766000 100644\n--- a/builtin/am.c\n+++ b/builtin/am.c\n@@ -1737,6 +1737,14 @@ static void am_run(struct am_state *state, int resume)\n \t\t\texit(1);\n \n \t\tsay(state, stdout, _(\"Applying: %.*s\"), linelen(state->msg), state->msg);\n+\t\t{\n+\t\t\tint i;\n+\t\t\tfor (i = 0; i < 60; i++) {\n+\t\t\t\tfprintf(stderr, \"sleeping... %d\\r\", i);\n+\t\t\t\tsleep(1);\n+\t\t\t}\n+\t\t\tfprintf(stderr, \"\\n\");\n+\t\t}\n \n \t\tapply_status = run_apply(state, NULL);\n \nAnd then we can reliably reproduce the issue even when rebasing only a\nsingle commit:\n\n  $ ./bin-wrappers/git rebase v2.25.0 9c8a294\n  First, rewinding head to replay your work on top of it...\n  Applying: sha1-file: remove OBJECT_INFO_SKIP_CACHED\n  ^Ceeping... 3\n  ((v2.25.0)|REBASE 1/1)$ ./bin-wrappers/git rebase --abort \n  error: could not read '.git/rebase-apply/head-name': No such file or directory\n\nNote that the sleep() calls were added to 'builtin/am.c', i.e. this\nissue is present in the 'am' rebase backend.  I tried to break 'git\nrebase -m ...' by adding sleep()s to various places in pick_commits()\nin 'sequencer.c', but, FWIW, the subsequent 'git rebase --abort'\nalways worked as expected.\n\nSo we may have yet another reason to switch the default rebase backend\nfrom 'am' to 'merge'.\n\n\n> Finally, note the 'v2.24.0^{commit}' parameter, in particular the\n> '^{commit}' part.  That's important, because without it we stumble\n> upon _another_ bug:\n> \n>   $ git rebase v2.22.0 v2.24.0\n>   error: Object 1cc4bc0fcd93f816d514d77c29f2cc9ffdd8ae09 not a commit\n>   First, rewinding head to replay your work on top of it...\n>   Generating patches: 100% (1049/1049), done.\n>   Applying: send-email: move the read_config() function above getopts\n>   < ... applying further patches and hitting a merge conflict ... >\n>   Resolve all conflicts manually, mark them as resolved with\n>   \"git add/rm <conflicted_files>\", then run \"git rebase --continue\".\n>   You can instead skip this commit: run \"git rebase --skip\".\n>   To abort and get back to the state before \"git rebase\", run \"git rebase --abort\".\n>   (detached HEAD *+|REBASE 7/1049)$ git rebase --abort \n>   error: update_ref failed for ref 'HEAD': cannot update ref 'HEAD': trying to write non-commit object 1cc4bc0fcd93f816d514d77c29f2cc9ffdd8ae09 to branch 'HEAD'\n> \n> So 'git rebase' shows an error right at the beginning when rebasing a\n> tag, but then continues anyway.  However, 'git rebase --abort' can't\n> restore the original state.\n\nNow let's rebase a tag with the 'merge' backend, and then try to abort\nit:\n\n  $ ./BUILDS/v2.25.0/bin/git rebase -m v2.22.0 v2.24.0\n  error: Object 1cc4bc0fcd93f816d514d77c29f2cc9ffdd8ae09 not a commit\n  Auto-merging t/t9001-send-email.sh\n  Auto-merging git-send-email.perl\n  CONFLICT (content): Merge conflict in git-send-email.perl\n  Auto-merging Documentation/git-send-email.txt\n  error: could not apply 3ff15040e2... send-email: fix regression in sendemail.identity parsing\n  Resolve all conflicts manually, mark them as resolved with\n  \"git add/rm <conflicted_files>\", then run \"git rebase --continue\".\n  You can instead skip this commit: run \"git rebase --skip\".\n  To abort and get back to the state before \"git rebase\", run \"git rebase --abort\".\n  Recorded preimage for 'git-send-email.perl'\n  Could not apply 3ff15040e2... send-email: fix regression in sendemail.identity parsing\n  (detached HEAD *+|REBASE 7/1049)$ ./BUILDS/v2.25.0/bin/git rebase --abort\n  ((v2.24.0))$\n\nSo it prints the same error as the 'am' backend (or perhaps that error\ncomes from the common, backend-independent parts of rebase?  I didn't\nlook), and it continues all the same, but in the end '--abort' is\ncapable to abort the operation.  So we do have yet another reason to\nswitch the default backend.\n\n"},{"id":"391339","messageId":"CABPp-BHum+h4mni4zc1R+6WfsVe6BHh8QeqidAzCR37WtwgKAQ@mail.gmail.com","threadId":"52758","inReplyTo":"20200207132152.GC2868@szeder.dev","subject":"Re: [BUG?] 'git rebase --abort' couldn't abort aborted rebase","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2020-02-07T17:52:51Z","receivedAt":"2020-02-07T17:53:05Z","isPatch":false,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Fri, Feb 7, 2020 at 5:21 AM SZEDER Gábor <szeder.dev@gmail.com> wrote:\n>\n> On Fri, Feb 07, 2020 at 12:49:54PM +0100, SZEDER Gábor wrote:\n> > On Fri, Feb 07, 2020 at 12:10:08PM +0100, SZEDER Gábor wrote:\n> > > That's a good subject, isn't it? :)\n\nIndeed.  :-)\n\n> > > So, to clarify: apparently it is possible to abort an ongoing 'git\n> > > rebase' process with ctrl-C in just the right moment that a subsequent\n> > > 'git rebase --abort' will refuse to clear it up.\n> > >\n> > > I somehow messed up the upstream and branch parameters of 'git\n> > > rebase', and ended up trying to rebase a fairly recent (post v2.24.0)\n> > > branch on top of v2.22.0.  Upon seeing the unexpectedly large number\n> > > of patches I realized that something is wrong, hit ctrl-C right away,\n> > > and this is what happened:\n> > >\n> > >   $ git rebase v2.22.0 <a-branch-on-top-of-2.24.0>\n> > >   First, rewinding head to replay your work on top of it...\n> > >   Generating patches: 100% (1108/1108), done.\n> > >   Applying: send-email: move the read_config() function above getopts\n> > >   Applying: send-email: rename the @bcclist variable for consistency\n> > >   Applying: send-email: do defaults -> config -> getopt in that order\n> > >   Using index info to reconstruct a base tree...\n> > >   M       git-send-email.perl\n> > >   M       t/t9001-send-email.sh\n> > >   Falling back to patching base and 3-way merge...\n> > >   Auto-merging t/t9001-send-email.sh\n> > >   Auto-merging git-send-email.perl\n> > >   ^C\n> > >   ((5f07da12ac...) *|REBASE 3/1108)$ git rebase --abort\n> > >   error: could not read '/home/szeder/src/git/.git/worktrees/WT/rebase-apply/head-name': No such file or directory\n> > >\n> > > \"Fortunately\" it was in a separate worktree, so I could easily get out\n> > > of the situation by forcibly deleting that worktree.  Unfortunately,\n> > > that was exactly what I did, instead of securing the failed state for\n> > > later analysis...  sorry.\n> >\n> > > All this is with a git built from current 'next', with a bunch of\n> > > unrelated (none of them touches rebase or the sequencer) patches on\n> > > top.\n> >\n> > Trying to reproduce it is a hit or miss... well, mostly miss :)\n> >\n> > There is a rather short window when 'git rebase' applies patches\n> > before hitting a first merge conflict.  If the ctrl-C arrives before\n> > 'git rebase' starts applying patches, then it cleans everything up,\n> > and we are not rebasing, so there is no need for 'git rebase --abort'.\n> > Once 'git rebase' stops because of the merge conflict we get our shell\n> > back, and 'git rebase --abort' works as it should.  But after a good\n> > couple of tries I managed to hit ctrl-C while 'git rebase' was\n> > applying patches:\n>\n> This patch below increases the size of the window where a ctrl-C gets\n> us into that problematic situation:\n>\n> diff --git a/builtin/am.c b/builtin/am.c\n> index 8181c2aef3..5d62766000 100644\n> --- a/builtin/am.c\n> +++ b/builtin/am.c\n> @@ -1737,6 +1737,14 @@ static void am_run(struct am_state *state, int resume)\n>                         exit(1);\n>\n>                 say(state, stdout, _(\"Applying: %.*s\"), linelen(state->msg), state->msg);\n> +               {\n> +                       int i;\n> +                       for (i = 0; i < 60; i++) {\n> +                               fprintf(stderr, \"sleeping... %d\\r\", i);\n> +                               sleep(1);\n> +                       }\n> +                       fprintf(stderr, \"\\n\");\n> +               }\n>\n>                 apply_status = run_apply(state, NULL);\n>\n> And then we can reliably reproduce the issue even when rebasing only a\n> single commit:\n>\n>   $ ./bin-wrappers/git rebase v2.25.0 9c8a294\n>   First, rewinding head to replay your work on top of it...\n>   Applying: sha1-file: remove OBJECT_INFO_SKIP_CACHED\n>   ^Ceeping... 3\n>   ((v2.25.0)|REBASE 1/1)$ ./bin-wrappers/git rebase --abort\n>   error: could not read '.git/rebase-apply/head-name': No such file or directory\n>\n> Note that the sleep() calls were added to 'builtin/am.c', i.e. this\n> issue is present in the 'am' rebase backend.  I tried to break 'git\n> rebase -m ...' by adding sleep()s to various places in pick_commits()\n> in 'sequencer.c', but, FWIW, the subsequent 'git rebase --abort'\n> always worked as expected.\n>\n> So we may have yet another reason to switch the default rebase backend\n> from 'am' to 'merge'.\n>\n>\n> > Finally, note the 'v2.24.0^{commit}' parameter, in particular the\n> > '^{commit}' part.  That's important, because without it we stumble\n> > upon _another_ bug:\n> >\n> >   $ git rebase v2.22.0 v2.24.0\n> >   error: Object 1cc4bc0fcd93f816d514d77c29f2cc9ffdd8ae09 not a commit\n> >   First, rewinding head to replay your work on top of it...\n> >   Generating patches: 100% (1049/1049), done.\n> >   Applying: send-email: move the read_config() function above getopts\n> >   < ... applying further patches and hitting a merge conflict ... >\n> >   Resolve all conflicts manually, mark them as resolved with\n> >   \"git add/rm <conflicted_files>\", then run \"git rebase --continue\".\n> >   You can instead skip this commit: run \"git rebase --skip\".\n> >   To abort and get back to the state before \"git rebase\", run \"git rebase --abort\".\n> >   (detached HEAD *+|REBASE 7/1049)$ git rebase --abort\n> >   error: update_ref failed for ref 'HEAD': cannot update ref 'HEAD': trying to write non-commit object 1cc4bc0fcd93f816d514d77c29f2cc9ffdd8ae09 to branch 'HEAD'\n> >\n> > So 'git rebase' shows an error right at the beginning when rebasing a\n> > tag, but then continues anyway.  However, 'git rebase --abort' can't\n> > restore the original state.\n>\n> Now let's rebase a tag with the 'merge' backend, and then try to abort\n> it:\n>\n>   $ ./BUILDS/v2.25.0/bin/git rebase -m v2.22.0 v2.24.0\n>   error: Object 1cc4bc0fcd93f816d514d77c29f2cc9ffdd8ae09 not a commit\n>   Auto-merging t/t9001-send-email.sh\n>   Auto-merging git-send-email.perl\n>   CONFLICT (content): Merge conflict in git-send-email.perl\n>   Auto-merging Documentation/git-send-email.txt\n>   error: could not apply 3ff15040e2... send-email: fix regression in sendemail.identity parsing\n>   Resolve all conflicts manually, mark them as resolved with\n>   \"git add/rm <conflicted_files>\", then run \"git rebase --continue\".\n>   You can instead skip this commit: run \"git rebase --skip\".\n>   To abort and get back to the state before \"git rebase\", run \"git rebase --abort\".\n>   Recorded preimage for 'git-send-email.perl'\n>   Could not apply 3ff15040e2... send-email: fix regression in sendemail.identity parsing\n>   (detached HEAD *+|REBASE 7/1049)$ ./BUILDS/v2.25.0/bin/git rebase --abort\n>   ((v2.24.0))$\n>\n> So it prints the same error as the 'am' backend (or perhaps that error\n> comes from the common, backend-independent parts of rebase?  I didn't\n> look), and it continues all the same, but in the end '--abort' is\n> capable to abort the operation.  So we do have yet another reason to\n> switch the default backend.\n\nOoh, interesting; thanks for investigating and providing a heads up.\nI should probably add a note about this to the \"differences between\nbackends\"; I'll roll it into whatever changes I might need to make\nwith Phillip's review of the series.\n"}]}