{"thread":{"id":"60188","subject":"[PATCH] sequencer: update abort safety file more sparingly","startedAt":"2023-09-03T15:11:38Z","lastAt":"2023-09-04T12:48:21Z","messageCount":7,"participants":["Oswald Buddenhagen","Phillip Wood"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"481351","messageId":"20230903151132.739166-1-oswald.buddenhagen@gmx.de","threadId":"60188","inReplyTo":null,"subject":"[PATCH] sequencer: update abort safety file more sparingly","fromName":"Oswald Buddenhagen","fromEmail":"oswald.buddenhagen@gmx.de","sentAt":"2023-09-03T15:11:32Z","receivedAt":"2023-09-03T15:11:38Z","isPatch":true,"sender":{"key":"oswald.buddenhagen@gmx.de","avatar":"https://avatars.githubusercontent.com/u/812380?v=4"},"body":"The only situation where the file's content matters is --continue'ing\n(after a multi-cherry-pick merge conflict). This means that it is\nsufficient to write it in a single place, when we are prematurely\nexiting the main workhorse. This is much easier to reason about than the\nthree dispersed calls originally introduced in 1e41229d (\"sequencer:\nmake sequencer abort safer\", 2016-12-07). We now can also remove the\ninefficient file-based check whether the file needs writing, which\nwasn't even reliable: a single pick executed during an interrupted\nsequence would bypass the safety.\n\nSigned-off-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de>\n\n---\nCc: Stephan Beyer <s-beyer@gmx.net>\nCc: Johannes Schindelin <johannes.schindelin@gmx.de>\nCc: Phillip Wood <phillip.wood123@gmail.com>\n---\n sequencer.c                     | 9 ++-------\n t/t3510-cherry-pick-sequence.sh | 9 +++++++++\n 2 files changed, 11 insertions(+), 7 deletions(-)\n\ndiff --git a/sequencer.c b/sequencer.c\nindex a66dcf8ab2..716384cc7b 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -575,10 +575,6 @@ static void update_abort_safety_file(void)\n {\n \tstruct object_id head;\n \n-\t/* Do nothing on a single-pick */\n-\tif (!file_exists(git_path_seq_dir()))\n-\t\treturn;\n-\n \tif (!repo_get_oid(the_repository, \"HEAD\", &head))\n \t\twrite_file(git_path_abort_safety_file(), \"%s\", oid_to_hex(&head));\n \telse\n@@ -618,7 +614,6 @@ static int fast_forward_to(struct repository *r,\n \tstrbuf_release(&sb);\n \tstrbuf_release(&err);\n \tref_transaction_free(transaction);\n-\tupdate_abort_safety_file();\n \treturn 0;\n }\n \n@@ -2435,7 +2430,6 @@ static int do_pick_commit(struct repository *r,\n \tfree_message(commit, &msg);\n \tfree(author);\n \tstrbuf_release(&msgbuf);\n-\tupdate_abort_safety_file();\n \n \treturn res;\n }\n@@ -5269,8 +5263,9 @@ int sequencer_pick_revisions(struct repository *r,\n \t\treturn -1;\n \tif (save_opts(opts))\n \t\treturn -1;\n-\tupdate_abort_safety_file();\n \tres = pick_commits(r, &todo_list, opts);\n+\tif (todo_list.current < todo_list.nr)\n+\t\tupdate_abort_safety_file();\n \ttodo_list_release(&todo_list);\n \treturn res;\n }\ndiff --git a/t/t3510-cherry-pick-sequence.sh b/t/t3510-cherry-pick-sequence.sh\nindex 3b0fa66c33..170b664c33 100755\n--- a/t/t3510-cherry-pick-sequence.sh\n+++ b/t/t3510-cherry-pick-sequence.sh\n@@ -318,6 +318,15 @@ test_expect_success '--abort does not unsafely change HEAD' '\n \ttest_cmp_rev base HEAD\n '\n \n+test_expect_success '--abort after single pick does not unsafely change HEAD' '\n+\tpristine_detach initial &&\n+\ttest_must_fail git cherry-pick picked anotherpick &&\n+\tgit reset --hard &&\n+\tgit cherry-pick unrelatedpick &&\n+\tgit cherry-pick --abort 2>actual &&\n+\ttest_i18ngrep \"You seem to have moved HEAD\" actual\n+'\n+\n test_expect_success 'cherry-pick --abort to cancel multiple revert' '\n \tpristine_detach anotherpick &&\n \ttest_expect_code 1 git revert base..picked &&\n-- \n2.40.0.152.g15d061e6df\n\n"},{"id":"481355","messageId":"29fb7a38-1e92-457a-93ff-0e64ac09b907@gmail.com","threadId":"60188","inReplyTo":"20230903151132.739166-1-oswald.buddenhagen@gmx.de","subject":"Re: [PATCH] sequencer: update abort safety file more sparingly","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2023-09-03T18:40:00Z","receivedAt":"2023-09-03T18:46:29Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Oswald\n\nOn 03/09/2023 16:11, Oswald Buddenhagen wrote:\n> The only situation where the file's content matters is --continue'ing\n> (after a multi-cherry-pick merge conflict).\n\nI don't think \"cherry-pick --continue\" consults the abort safety file, \nit only matters for \"cherry-pick --skip\" and \"cherry-pick --abort\".\n\n> This means that it is\n> sufficient to write it in a single place, when we are prematurely\n> exiting the main workhorse.\n\nI think this introduces a regression because the safety file will not \nget updated when \"cherry-pick --continue\" stops for the user to resolve \nconflicts.\n\n> This is much easier to reason about than the\n> three dispersed calls originally introduced in 1e41229d (\"sequencer:\n> make sequencer abort safer\", 2016-12-07). We now can also remove the\n> inefficient file-based check whether the file needs writing, which\n> wasn't even reliable: a single pick executed during an interrupted\n> sequence would bypass the safety.\n\nAn alternate view is that the abort safety file exists to prevent the \nuser losing commits that have not been cherry-picked and it is desirable \nto be able to abort after cherry-picking a single pick in the middle of \na sequence of cherry-picks.\n\nBest Wishes\n\nPhillip\n\n> Signed-off-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de>\n> \n> ---\n> Cc: Stephan Beyer <s-beyer@gmx.net>\n> Cc: Johannes Schindelin <johannes.schindelin@gmx.de>\n> Cc: Phillip Wood <phillip.wood123@gmail.com>\n> ---\n>   sequencer.c                     | 9 ++-------\n>   t/t3510-cherry-pick-sequence.sh | 9 +++++++++\n>   2 files changed, 11 insertions(+), 7 deletions(-)\n> \n> diff --git a/sequencer.c b/sequencer.c\n> index a66dcf8ab2..716384cc7b 100644\n> --- a/sequencer.c\n> +++ b/sequencer.c\n> @@ -575,10 +575,6 @@ static void update_abort_safety_file(void)\n>   {\n>   \tstruct object_id head;\n>   \n> -\t/* Do nothing on a single-pick */\n> -\tif (!file_exists(git_path_seq_dir()))\n> -\t\treturn;\n> -\n>   \tif (!repo_get_oid(the_repository, \"HEAD\", &head))\n>   \t\twrite_file(git_path_abort_safety_file(), \"%s\", oid_to_hex(&head));\n>   \telse\n> @@ -618,7 +614,6 @@ static int fast_forward_to(struct repository *r,\n>   \tstrbuf_release(&sb);\n>   \tstrbuf_release(&err);\n>   \tref_transaction_free(transaction);\n> -\tupdate_abort_safety_file();\n>   \treturn 0;\n>   }\n>   \n> @@ -2435,7 +2430,6 @@ static int do_pick_commit(struct repository *r,\n>   \tfree_message(commit, &msg);\n>   \tfree(author);\n>   \tstrbuf_release(&msgbuf);\n> -\tupdate_abort_safety_file();\n>   \n>   \treturn res;\n>   }\n> @@ -5269,8 +5263,9 @@ int sequencer_pick_revisions(struct repository *r,\n>   \t\treturn -1;\n>   \tif (save_opts(opts))\n>   \t\treturn -1;\n> -\tupdate_abort_safety_file();\n>   \tres = pick_commits(r, &todo_list, opts);\n> +\tif (todo_list.current < todo_list.nr)\n> +\t\tupdate_abort_safety_file();\n>   \ttodo_list_release(&todo_list);\n>   \treturn res;\n>   }\n> diff --git a/t/t3510-cherry-pick-sequence.sh b/t/t3510-cherry-pick-sequence.sh\n> index 3b0fa66c33..170b664c33 100755\n> --- a/t/t3510-cherry-pick-sequence.sh\n> +++ b/t/t3510-cherry-pick-sequence.sh\n> @@ -318,6 +318,15 @@ test_expect_success '--abort does not unsafely change HEAD' '\n>   \ttest_cmp_rev base HEAD\n>   '\n>   \n> +test_expect_success '--abort after single pick does not unsafely change HEAD' '\n> +\tpristine_detach initial &&\n> +\ttest_must_fail git cherry-pick picked anotherpick &&\n> +\tgit reset --hard &&\n> +\tgit cherry-pick unrelatedpick &&\n> +\tgit cherry-pick --abort 2>actual &&\n> +\ttest_i18ngrep \"You seem to have moved HEAD\" actual\n> +'\n> +\n>   test_expect_success 'cherry-pick --abort to cancel multiple revert' '\n>   \tpristine_detach anotherpick &&\n>   \ttest_expect_code 1 git revert base..picked &&\n"},{"id":"481356","messageId":"ZPTdmnHfDcTBqaSl@ugly","threadId":"60188","inReplyTo":"29fb7a38-1e92-457a-93ff-0e64ac09b907@gmail.com","subject":"Re: [PATCH] sequencer: update abort safety file more sparingly","fromName":"Oswald Buddenhagen","fromEmail":"oswald.buddenhagen@gmx.de","sentAt":"2023-09-03T19:25:14Z","receivedAt":"2023-09-03T19:25:28Z","isPatch":true,"sender":{"key":"oswald.buddenhagen@gmx.de","avatar":"https://avatars.githubusercontent.com/u/812380?v=4"},"body":"On Sun, Sep 03, 2023 at 07:40:00PM +0100, Phillip Wood wrote:\n>On 03/09/2023 16:11, Oswald Buddenhagen wrote:\n>> The only situation where the file's content matters is --continue'ing\n>> (after a multi-cherry-pick merge conflict).\n>\n>I don't think \"cherry-pick --continue\" consults the abort safety file, \n>\nduh, obvious blunder.\n\n>it only matters for \"cherry-pick --skip\"\n>\nthat doesn't seem right. a --skip is just a --continue with a prior \nreset, more or less.\n\n>and \"cherry-pick --abort\".\n>\nthat one, of course.\n\n>> This means that it is\n>> sufficient to write it in a single place, when we are prematurely\n>> exiting the main workhorse.\n>\n>I think this introduces a regression because the safety file will not \n>get updated when \"cherry-pick --continue\" stops for the user to resolve \n>conflicts.\n>\ntrue, there is indeed this second entry point.\ni'll try to find a better \"choke point\".\n\n>> which wasn't even reliable: a single pick executed during an \n>> interrupted sequence would bypass the safety.\n>\n>An alternate view is that the abort safety file exists to prevent the \n>user losing commits that have not been cherry-picked and it is \n>desirable to be able to abort after cherry-picking a single pick in the \n>middle of a sequence of cherry-picks.\n>\nif you did a fresh commit before or after the single pick, you'd lose \nit.\nalso, the feature doesn't actually prevent aborting, only the automatic \nreset.\n\nregards\n"},{"id":"481357","messageId":"fdf80c36-0e28-44f3-9cef-85d38d2d48f1@gmail.com","threadId":"60188","inReplyTo":"ZPTdmnHfDcTBqaSl@ugly","subject":"Re: [PATCH] sequencer: update abort safety file more sparingly","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2023-09-03T19:48:14Z","receivedAt":"2023-09-03T19:48:28Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"On 03/09/2023 20:25, Oswald Buddenhagen wrote:\n> On Sun, Sep 03, 2023 at 07:40:00PM +0100, Phillip Wood wrote:\n>> On 03/09/2023 16:11, Oswald Buddenhagen wrote:\n>>> The only situation where the file's content matters is --continue'ing\n>>> (after a multi-cherry-pick merge conflict).\n>>\n>> I don't think \"cherry-pick --continue\" consults the abort safety file,\n> duh, obvious blunder.\n> \n>> it only matters for \"cherry-pick --skip\"\n>>\n> that doesn't seem right. a --skip is just a --continue with a prior \n> reset, more or less.\n\nsequencer_skip() calls rollback_is_safe() which checks the abort safety \nfile.\n\n>> and \"cherry-pick --abort\".\n>>\n> that one, of course.\n> \n>>> This means that it is\n>>> sufficient to write it in a single place, when we are prematurely\n>>> exiting the main workhorse.\n>>\n>> I think this introduces a regression because the safety file will not \n>> get updated when \"cherry-pick --continue\" stops for the user to \n>> resolve conflicts.\n>>\n> true, there is indeed this second entry point.\n> i'll try to find a better \"choke point\".\n\nI think that is probably tricky, I'm not really clear what the \naim/purpose of this refactoring is.\n\n>>> which wasn't even reliable: a single pick executed during an \n>>> interrupted sequence would bypass the safety.\n>>\n>> An alternate view is that the abort safety file exists to prevent the \n>> user losing commits that have not been cherry-picked and it is \n>> desirable to be able to abort after cherry-picking a single pick in \n>> the middle of a sequence of cherry-picks.\n>>\n> if you did a fresh commit before or after the single pick, you'd lose it.\n> also,\n\nOh, I can see that you'd lose a commit made before a single pick but I \ndon't see how you'd lose a commit made after it. I'm still not convinced \nit is a particularly helpful change.\n\n> the feature doesn't actually prevent aborting, only the automatic \n> reset.\n\nOh right, it removes the state directory but leaves HEAD untouched if it \ndoes not match the commit recorded in the abort safety file.\n\nBest Wishes\n\nPhillip\n\n> regards\n"},{"id":"481358","messageId":"ZPTqEIvW3zJ4eafT@ugly","threadId":"60188","inReplyTo":"fdf80c36-0e28-44f3-9cef-85d38d2d48f1@gmail.com","subject":"Re: [PATCH] sequencer: update abort safety file more sparingly","fromName":"Oswald Buddenhagen","fromEmail":"oswald.buddenhagen@gmx.de","sentAt":"2023-09-03T20:18:24Z","receivedAt":"2023-09-03T20:18:48Z","isPatch":true,"sender":{"key":"oswald.buddenhagen@gmx.de","avatar":"https://avatars.githubusercontent.com/u/812380?v=4"},"body":"On Sun, Sep 03, 2023 at 08:48:14PM +0100, Phillip Wood wrote:\n>On 03/09/2023 20:25, Oswald Buddenhagen wrote:\n>> On Sun, Sep 03, 2023 at 07:40:00PM +0100, Phillip Wood wrote:\n>>> it only matters for \"cherry-pick --skip\"\n>>>\n>> that doesn't seem right. a --skip is just a --continue with a prior \n>> reset, more or less.\n>\n>sequencer_skip() calls rollback_is_safe() which checks the abort safety \n>file.\n>\nthat's weird. can you think of a good reason for doing that?\n\n>> i'll try to find a better \"choke point\".\n>\n>I think that is probably tricky,\n>\nyeah\n\n>I'm not really clear what the aim/purpose of this refactoring is.\n>\nto make my head not explode.\nmore specifically, to get it out of the way of the rebase path, which is \nwhat i'm actually concerned with.\n\ngenerally, i think this whole ad-hoc state management is a nightmare, \nand i'd be surprised if there weren't some more loose ends.\ni think i'd aim for an object-oriented-ish design with an encapsulated \nstate, lazy loading getters, lazy setters, and a commit entry point (or \nmaybe several partial ones). no idea how that would play out.\n\n>> if you did a fresh commit before or after the single pick, you'd lose \n>> it.\n>\n>Oh, I can see that you'd lose a commit made before a single pick but I \n>don't see how you'd lose a commit made after it.\n>\nright. thinko. it's a bit late here. ^^\n\nregards\n"},{"id":"481363","messageId":"4e0628ab-c39c-410d-864b-b7c74f9e04b1@gmail.com","threadId":"60188","inReplyTo":"ZPTqEIvW3zJ4eafT@ugly","subject":"Re: [PATCH] sequencer: update abort safety file more sparingly","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2023-09-04T10:05:22Z","receivedAt":"2023-09-04T10:05:30Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"On 03/09/2023 21:18, Oswald Buddenhagen wrote:\n> On Sun, Sep 03, 2023 at 08:48:14PM +0100, Phillip Wood wrote:\n>> On 03/09/2023 20:25, Oswald Buddenhagen wrote:\n>>> On Sun, Sep 03, 2023 at 07:40:00PM +0100, Phillip Wood wrote:\n>>>> it only matters for \"cherry-pick --skip\"\n>>>>\n>>> that doesn't seem right. a --skip is just a --continue with a prior \n>>> reset, more or less.\n>>\n>> sequencer_skip() calls rollback_is_safe() which checks the abort \n>> safety file.\n>>\n> that's weird. can you think of a good reason for doing that?\n\nI think it is clear from the code - so it does not reset changes after \nthe user has committed the conflict resolution.\n\n>>> i'll try to find a better \"choke point\".\n>>\n>> I think that is probably tricky,\n>>\n> yeah\n> \n>> I'm not really clear what the aim/purpose of this refactoring is.\n>>\n> to make my head not explode.\n> more specifically, to get it out of the way of the rebase path, which is \n> what i'm actually concerned with.\n\nrebase and cherry-pick share the same code path most of the time. In \nparticular \"cherry-pick --continue\" and \"rebase --continue\" both use \nsequencer_continue() as their entry point so I think the best you can do \nis guard the calls to update_abort_safety_file() with \"if \n(!is_rebase_i(opts))\" or add \"if (is_rebase_i(opts)) return\" to the \nstart of update_abort_safety_file().\n\n> generally, i think this whole ad-hoc state management is a nightmare, \n> and i'd be surprised if there weren't some more loose ends.\n> i think i'd aim for an object-oriented-ish design with an encapsulated \n> state, lazy loading getters, lazy setters, and a commit entry point (or \n> maybe several partial ones). no idea how that would play out.\n\nI've been working on something similar to only write the state to disc \nwhen the sequencer stops for user interaction. I'm hoping to have the \nfirst set of patches ready to submit in the next development cycle. You \ncan see the branch at [1]. It is very much a work in progress at the \nmoment, the code is mostly OK (I'm running it in my git build) but some \ncommits are empty, others need splitting and the commit messages need a \nlot of work. The basic idea is to add a private struct that holds the \nstate and write that to disc when pick_commits() returns.\n\nBest Wishes\n\nPhillip\n\n[1] https://github.com/phillipwood/git/commits/wip/sequencer-context\n\n>>> if you did a fresh commit before or after the single pick, you'd lose \n>>> it.\n>>\n>> Oh, I can see that you'd lose a commit made before a single pick but I \n>> don't see how you'd lose a commit made after it.\n>>\n> right. thinko. it's a bit late here. ^^\n> \n> regards\n\n"},{"id":"481366","messageId":"ZPXSDKTjK4k1LGjk@ugly","threadId":"60188","inReplyTo":"4e0628ab-c39c-410d-864b-b7c74f9e04b1@gmail.com","subject":"Re: [PATCH] sequencer: update abort safety file more sparingly","fromName":"Oswald Buddenhagen","fromEmail":"oswald.buddenhagen@gmx.de","sentAt":"2023-09-04T12:48:12Z","receivedAt":"2023-09-04T12:48:21Z","isPatch":true,"sender":{"key":"oswald.buddenhagen@gmx.de","avatar":"https://avatars.githubusercontent.com/u/812380?v=4"},"body":"On Mon, Sep 04, 2023 at 11:05:22AM +0100, Phillip Wood wrote:\n>On 03/09/2023 21:18, Oswald Buddenhagen wrote:\n>> On Sun, Sep 03, 2023 at 08:48:14PM +0100, Phillip Wood wrote:\n>>> On 03/09/2023 20:25, Oswald Buddenhagen wrote:\n>>>> On Sun, Sep 03, 2023 at 07:40:00PM +0100, Phillip Wood wrote:\n>>>>> it only matters for \"cherry-pick --skip\"\n>>>>>\n>>>> that doesn't seem right. a --skip is just a --continue with a prior \n>>>> reset, more or less.\n>>>\n>>> sequencer_skip() calls rollback_is_safe() which checks the abort \n>>> safety file.\n>>>\n>> that's weird. can you think of a good reason for doing that?\n>\n>I think it is clear from the code - so it does not reset changes after \n>the user has committed the conflict resolution.\n>\nyeah, i've researched that meanwhile.\nthe background is that the machinery that was originally introduced for \nabort safety was later (ab-)used for checking whether a --skip makes \nsense (de81ca3f36, \"cherry-pick/revert: add --skip option\", 2019-07-02).  \nthis made the state file a misnomer (not that \"abort-safety\" was a \nparticularly good name to start with - i'd have used \"latest-head\" or \nsome such).\n\nbut the implementation made no sense to me, so i read the mailing list \narchive. the result is the attached patch.\nhowever, even so, it seems kinda wrong to me: going by HEAD means that \ndropping commits would also trigger it, which would make the given \nadvice misleading.\nin fact, the situation this code path is covering is fundamentally \ndifferent from the normal merge conflict: rather than letting the user \nresolve it and us finishing the commit, we are rescheduling the pick.  \nbut that means that --skip needs to skip whatever the next command is?  \nthat doesn't sound right.\nalso, i just tried --continue after a path conflict, and it apparently \ndid the same as --skip, so something is really wrong.\nalso, when we have no _HEAD, actually attempting to `reset --merge` is \npointless, no?\n\noh, and i just noticed that the git-prompt is buggy: it doesn't tell me \nabout the interrupted multi-pick nested into an interrupted rebase.\n\nugh, and rebase lets me continue despite still being in the multi-pick.\n\nand the path conflict check is made ineffective by the file in question \nbeing in .gitignore?! (i force-added config.mak.autogen for testing, and \ncherry-picking over it goes through just fine.)\n\n>> i think i'd aim for an object-oriented-ish design with an \n>> encapsulated state, lazy loading getters, lazy setters, and a commit \n>> entry point (or maybe several partial ones). no idea how that would \n>> play out.\n>\n>I've been working on something similar\n>\nawesome!\n(well, except for the rebase nightmare in my own series i expect because \nof this.)\n\n>to only write the state to disc when the sequencer stops for user \n>interaction.\n>\nnote that this must cover ctrl-c as well, because the sequencer state \nmust be consistent with HEAD. of course one could also delay updating \nHEAD, but that hinges on no relevant hooks being present, i think?  \ngit-replay has a huge advantage here ...\n\nregards\n\n\nFrom eb81dc1d5ecb7d9d3cf4608b93c30250392f6fc7 Mon Sep 17 00:00:00 2001\nFrom: Oswald Buddenhagen <oswald.buddenhagen@gmx.de>\nDate: Mon, 4 Sep 2023 13:07:04 +0200\nSubject: [PATCH] sequencer: improve comment in sequencer_skip()\n\nIt wasn't clear under which circumstances the described path would be\nrelevant.\n\nChange-Id: Ie9fd8a619dad4daf163c5efdb2f9a9eccf17307d\nSigned-off-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de>\n---\n sequencer.c | 13 +++++++------\n 1 file changed, 7 insertions(+), 6 deletions(-)\n\ndiff --git a/sequencer.c b/sequencer.c\nindex c0ff165b83..11d2368ab1 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -3359,12 +3359,13 @@ int sequencer_skip(struct repository *r, struct replay_opts *opts)\n \t * If the corresponding .git/<ACTION>_HEAD exists, we know that the\n \t * action is in progress and we can skip the commit.\n \t *\n-\t * Otherwise we check that the last instruction was related to the\n-\t * particular subcommand we're trying to execute and barf if that's not\n-\t * the case.\n-\t *\n-\t * Finally we check that the rollback is \"safe\", i.e., has the HEAD\n-\t * moved? In this case, it doesn't make sense to \"reset the merge\" and\n+\t * But if the action would have overwritten an untracked file, no\n+\t * corresponding _HEAD file exists.\n+\t * In this case we fall back to checking that the last instruction was\n+\t * related to the particular subcommand we're trying to execute and barf\n+\t * if that's not the case.\n+\t * We also check that the rollback is \"safe\", i.e., whether the HEAD\n+\t * moved. If it did, it doesn't make sense to \"reset the merge\" and\n \t * \"skip the commit\" as the user already handled this by committing. But\n \t * we'd not want to barf here, instead give advice on how to proceed. We\n \t * only need to check that when .git/<ACTION>_HEAD doesn't exist because\n-- \n2.42.0.324.gb1ea313d68\n\n"}]}