{"thread":{"id":"55291","subject":"[Bug] Stashing during merge loses MERGING state","startedAt":"2021-03-11T14:09:59Z","lastAt":"2021-03-12T07:18:22Z","messageCount":9,"participants":["Tassilo Horn","Jeff King","Phil Hord","Junio C Hamano","Chris Torek","Elijah Newren"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"418845","messageId":"875z1xwznd.fsf@gnu.org","threadId":"55291","inReplyTo":null,"subject":"[Bug] Stashing during merge loses MERGING state","fromName":"Tassilo Horn","fromEmail":"tsdh@gnu.org","sentAt":"2021-03-11T14:00:58Z","receivedAt":"2021-03-11T14:09:59Z","isPatch":false,"sender":{"key":"tsdh@gnu.org","avatar":"https://avatars.githubusercontent.com/u/103854?v=4"},"body":"Thank you for filling out a Git bug report!\nPlease answer the following questions to help us understand your issue.\n\nWhat did you do before the bug happened? (Steps to reproduce your issue)\n\nI did a large merge, resolved the conflicts but still had compile\nerrors.  In order to check how stuff has worked before the merge, I\nstashed all changes, and eventually popped the stash.  Then the MERGING\nstate was gone and committing created a single-parent commit rather than\na merge commit with two parents.  I was lucky to see that before\npushing, so all is good.\n\nHere is a simple recipe with a publicly available repo:\n\n```sh\ngit clone https://github.com/magit/magit.git\n# Current master is 4735b9254105eb7dd538f979d8b4c6ab96b827b9\ncd magit\ngit merge origin/km/reshelve-rewrite # currently 0073bff21c826a57a4b48076074bdbba092d4b67\n# Conflict in magit-extras.el\ngit add lisp/magit-extras.el\ngit stash\n# The MERGING state is gone\ngit stash pop\n# And it won't come back, so when I commit now, my \"merge\" has just\n# one parent.\n```\n\nWhat did you expect to happen? (Expected behavior)\n\nI expected that stashing during a merge will keep the MERGING state.\nOr that popping the stash again would also restore the MERGING state.\n\nWhat happened instead? (Actual behavior)\n\nThe MERGING state is lost.\n\nWhat's different between what you expected and what actually happened?\n\nI've lost the MERGING state, thus committing results in a one-parent\ncommit rather than a 2-parent merge commit.\n\nAnything else you want to add:\n\nIn my original situation, I've copied the working tree to /tmp, resetted\nto origin/master, re-initiated the merge, copied the modified files from\nthe /tmp backup, staged the changes, committed, and pushed.\n\nI wonder if there would have been a better approach to come from the\n\"accidentally having a single-parent commit containing all merged and\nresolution changes\" state to a proper merge commit state.  In the end,\nthe tree was correct, just the second parent to the commit on the merged\nbranch was missing.\n\nPlease review the rest of the bug report below.\nYou can delete any lines you don't wish to share.\n\n\n[System Info]\ngit version:\ngit version 2.30.2\ncpu: x86_64\nno commit associated with this build\nsizeof-long: 8\nsizeof-size_t: 8\nshell-path: /bin/sh\nuname: Linux 5.11.4-arch1-1 #1 SMP PREEMPT Sun, 07 Mar 2021 18:00:49 +0000 x86_64\ncompiler info: gnuc: 10.2\nlibc info: glibc: 2.33\n$SHELL (typically, interactive shell): /usr/bin/fish\n\n\n[Enabled Hooks]\n"},{"id":"418898","messageId":"YEpusE7ZIE5RgOws@coredump.intra.peff.net","threadId":"55291","inReplyTo":"875z1xwznd.fsf@gnu.org","subject":"Re: [Bug] Stashing during merge loses MERGING state","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2021-03-11T19:25:36Z","receivedAt":"2021-03-11T19:26:17Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Mar 11, 2021 at 03:00:58PM +0100, Tassilo Horn wrote:\n\n> Here is a simple recipe with a publicly available repo:\n> \n> ```sh\n> git clone https://github.com/magit/magit.git\n> # Current master is 4735b9254105eb7dd538f979d8b4c6ab96b827b9\n> cd magit\n> git merge origin/km/reshelve-rewrite # currently 0073bff21c826a57a4b48076074bdbba092d4b67\n> # Conflict in magit-extras.el\n> git add lisp/magit-extras.el\n> git stash\n> # The MERGING state is gone\n> git stash pop\n> # And it won't come back, so when I commit now, my \"merge\" has just\n> # one parent.\n> ```\n> \n> What did you expect to happen? (Expected behavior)\n> \n> I expected that stashing during a merge will keep the MERGING state.\n\nThanks for providing a clear recipe and expectation. However, I think\nGit is working here as intended. The MERGE_HEAD file (which is how \"git\nstatus\", the prompt, etc figure out that we're in the middle of a merge)\nis cleaned up when stash runs \"git reset --hard\" under the hood.\n\nHowever, I don't think we would want to _not_ clear that file. The\nconflicted merge placed some changes into the index and working tree\nrepresenting what happened on the branch you're merging in. Then making\nthe stash (and the reset of the working tree) removes those changes. If\nwe were to leave MERGE_HEAD in place and you ran \"git commit\", then it\nwould create a merge commit that claims to have incorporated everything\nfrom the other branch, but has quietly dropped those changes as part of\nthe merge resolution.\n\n> Or that popping the stash again would also restore the MERGING state.\n\nThis would make more sense: the stash records that part of the state,\nand then we make it available again later when the stash is applied.\nHowever, that feature doesn't exist yet.\n\nI can't offhand think of a reason it couldn't be implemented. It's\npossible that it would mess with somebody else's workflow (e.g., they\nthink it's useful to stash some changes independent of the merging\nstate, and then apply it later, perhaps while replaying the same or a\nsimilar merge). So it might need to be tied to a command-line option or\nsimilar.\n\n-Peff\n"},{"id":"418905","messageId":"87a6r9o1yo.fsf@gnu.org","threadId":"55291","inReplyTo":"YEpusE7ZIE5RgOws@coredump.intra.peff.net","subject":"Re: [Bug] Stashing during merge loses MERGING state","fromName":"Tassilo Horn","fromEmail":"tsdh@gnu.org","sentAt":"2021-03-11T20:31:09Z","receivedAt":"2021-03-11T20:44:46Z","isPatch":false,"sender":{"key":"tsdh@gnu.org","avatar":"https://avatars.githubusercontent.com/u/103854?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\nHi Jeff,\n\n>> What did you expect to happen? (Expected behavior)\n>> \n>> I expected that stashing during a merge will keep the MERGING state.\n>\n> Thanks for providing a clear recipe and expectation. However, I think\n> Git is working here as intended. The MERGE_HEAD file (which is how \"git\n> status\", the prompt, etc figure out that we're in the middle of a merge)\n> is cleaned up when stash runs \"git reset --hard\" under the hood.\n>\n> However, I don't think we would want to _not_ clear that file. The\n> conflicted merge placed some changes into the index and working tree\n> representing what happened on the branch you're merging in. Then\n> making the stash (and the reset of the working tree) removes those\n> changes. If we were to leave MERGE_HEAD in place and you ran \"git\n> commit\", then it would create a merge commit that claims to have\n> incorporated everything from the other branch, but has quietly dropped\n> those changes as part of the merge resolution.\n\nYes, that makes sense.\n\n>> Or that popping the stash again would also restore the MERGING state.\n>\n> This would make more sense: the stash records that part of the state,\n> and then we make it available again later when the stash is applied.\n> However, that feature doesn't exist yet.\n\nToo bad.\n\n> I can't offhand think of a reason it couldn't be implemented. It's\n> possible that it would mess with somebody else's workflow (e.g., they\n> think it's useful to stash some changes independent of the merging\n> state, and then apply it later, perhaps while replaying the same or a\n> similar merge). So it might need to be tied to a command-line option\n> or similar.\n\nEverything breakes someones workflow [1], so an option would be fine.\n\nHowever, I'd suggest to protect users shooting in their foot with a\nwarning and confirmation query for the time being.  I consider myself a\nquite experienced git user but this stash trouble today came totally\nunexpected.  And I've asked on #git@irc.freenode.net and got no answer\nwhich is totally uncommon.  So I guess that this stash during merge\nthing is pretty much a gray area.\n\nBye,\nTassilo\n\n[1] https://xkcd.com/1172/\n"},{"id":"418929","messageId":"CABURp0pFdHAx_+-e+O35Qxtbe3_+cZy9SZcOSeR2R7v_neRwKg@mail.gmail.com","threadId":"55291","inReplyTo":"87a6r9o1yo.fsf@gnu.org","subject":"Re: [Bug] Stashing during merge loses MERGING state","fromName":"Phil Hord","fromEmail":"phil.hord@gmail.com","sentAt":"2021-03-12T05:00:34Z","receivedAt":"2021-03-12T05:03:15Z","isPatch":false,"sender":{"key":"phil.hord@gmail.com","avatar":"https://avatars.githubusercontent.com/u/123908?v=4"},"body":"On Thu, Mar 11, 2021 at 12:45 PM Tassilo Horn <tsdh@gnu.org> wrote:\n> >> Or that popping the stash again would also restore the MERGING state.\n> >\n> > This would make more sense: the stash records that part of the state,\n> > and then we make it available again later when the stash is applied.\n> > However, that feature doesn't exist yet.\n>\n> Too bad.\n\nConsider also what happens when `git stash apply` results in a merge\nconflict because of differences between your current index and the one\nyou had when you originally saved the stash.  This results in the\nusual merge conflict markers that then need to be cleaned up.\n\nCould we sanely deal with this in a world where we also tried to\nrestore .git/MERGE_HEAD when the stash was applied. Something like\n`git stash apply --continue`, possibly after resolving the stash\nconflicts?  But what if we stashed the merge conflict that resulted\nfrom the stash apply?  I guess it would still work, but the stash\nhistory would be, um, interesting.\n\nI wonder if a fix could be as simple as recording the MERGE_HEAD as\nthe third parent commit of the stash ref. I think that would provide\nall the information needed to put things back, except possibly for\nthings like the rerere state, which is also set up during a conflict,\nand other incidentals like .git/MERGE_MSG.  (And it feels like it\nmight break compatibility with older versions that don't expect a\nthird parent.)\n\nI would be a bit concerned about the possibility of silently creating\nan \"evil merge\".  Suppose you stash this conflict on some branch and\nthen pop it onto a different one.  I expect we would then be prepared\nto store all those changes from a different branch including existing\nresolved merge conflicts into the new one.  That could be surprising\nand subtle.\n\nBut maybe I'm overthinking it.  Wouldn't the stash apply result in\nmerge conflicts that would catch out all the troubling parts?\n\nI think being able to stash during a merge conflict could be very\nuseful.  I do sometimes need to get back to a working state\nmomentarily and a merge conflict represents a long pole to doing so.\nSimilarly, it could be useful to stash a conflicted `git rebase` so I\ncould return to it later and pick up where I left off.  Now we really\nwould need to store some extra metadata, though, like the todo-list\nand ORIG_HEAD.  And we would definitely need some extra command line\nswitch to tell stash (or rebase) that I want to include all the rebase\nstate and also \"pause\" the rebase by restoring to my starting point.\n\nThanks for raising the issue, Tassilo.  This has obviously given me\nmore ideas for things I forgot were missing.\n\n> > I can't offhand think of a reason it couldn't be implemented. It's\n> > possible that it would mess with somebody else's workflow (e.g., they\n> > think it's useful to stash some changes independent of the merging\n> > state, and then apply it later, perhaps while replaying the same or a\n> > similar merge). So it might need to be tied to a command-line option\n> > or similar.\n>\n> Everything breakes someones workflow [1], so an option would be fine.\n>\n> However, I'd suggest to protect users shooting in their foot with a\n> warning and confirmation query for the time being.  I consider myself a\n> quite experienced git user but this stash trouble today came totally\n> unexpected.  And I've asked on #git@irc.freenode.net and got no answer\n> which is totally uncommon.  So I guess that this stash during merge\n> thing is pretty much a gray area.\n\nI don't think we could easily add the warning when the stash is\napplied since we have forgotten the merge existed in the first place.\nSo we would have to do it during stash save.\n\n\"Warning: You are stashing during a merge conflict and your merge\nstate will not be restored by stash apply.\"\n\nSeems reasonable.\n\nPhil\n"},{"id":"418931","messageId":"xmqq5z1wc389.fsf@gitster.g","threadId":"55291","inReplyTo":"CABURp0pFdHAx_+-e+O35Qxtbe3_+cZy9SZcOSeR2R7v_neRwKg@mail.gmail.com","subject":"Re: [Bug] Stashing during merge loses MERGING state","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2021-03-12T06:09:42Z","receivedAt":"2021-03-12T06:10:47Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Phil Hord <phil.hord@gmail.com> writes:\n\n> On Thu, Mar 11, 2021 at 12:45 PM Tassilo Horn <tsdh@gnu.org> wrote:\n>> >> Or that popping the stash again would also restore the MERGING state.\n>> >\n>> > This would make more sense: the stash records that part of the state,\n>> > and then we make it available again later when the stash is applied.\n>> > However, that feature doesn't exist yet.\n>>\n>> Too bad.\n>\n> Consider also what happens when `git stash apply` results in a merge\n> conflict because of differences between your current index and the one\n> you had when you originally saved the stash.  This results in the\n> usual merge conflict markers that then need to be cleaned up.\n\nI agree with you that allowing a stash while a merge is in progress\nwill introduce many unpleasant corner cases the users wouldn't want\nto deal with.  We certainly do prevent \"git stash push\" from running\nwhen the index is still unmerged (which is a sign that a mergy\noperation (like pull, rebase, merge, am -3, cherry-pick and revert\nthat stops due to a conflict in the middle) is in progress), but\nonce the end user resolves the conflicts in the index (either\nmanually, or having the rerere.autoupdate feature in effect), such a\nsign of mergy operation still in progress that \"git stash\" currently\nuses will be gone.  We should teach \"git stash push\" to pay\nattention to other such signs like MERGE_HEAD etc. and stop before\ncreating a stash (and also do the same to \"git stash pop/apply\").\n\nTHanks.\n"},{"id":"418934","messageId":"CAPx1GvfguSyXznaaeQYB8JY96vmZmzOJyTnXX1yP3omeXptqXw@mail.gmail.com","threadId":"55291","inReplyTo":"CABURp0pFdHAx_+-e+O35Qxtbe3_+cZy9SZcOSeR2R7v_neRwKg@mail.gmail.com","subject":"Re: [Bug] Stashing during merge loses MERGING state","fromName":"Chris Torek","fromEmail":"chris.torek@gmail.com","sentAt":"2021-03-12T07:02:16Z","receivedAt":"2021-03-12T07:03:40Z","isPatch":false,"sender":{"key":"chris.torek@gmail.com","avatar":"https://avatars.githubusercontent.com/u/16826774?v=4"},"body":"On Thu, Mar 11, 2021 at 9:19 PM Phil Hord <phil.hord@gmail.com> wrote:\n> I wonder if a fix could be as simple as recording the MERGE_HEAD as\n> the third parent commit of the stash ref.\n\nThere is already a third parent, but only when using -u / -a: this\nthird-parent commit holds the untracked files (which are then removed\na la `git clean`).\n\nA better trick would, I think, be able to save a partial merge state\nin general, including the unmerged statuses of various files, the\nongoing action (merge or one of the other things that use it), and\nso on, in a form that could be restored later.  A plain `git stash` in\nany partially-merged state should tell you: no, use the fancier\nmerge-state-saver instead.\n\n> I think being able to stash during a merge conflict could be very\n> useful.  I do sometimes need to get back to a working state\n> momentarily and a merge conflict represents a long pole to doing so.\n> Similarly, it could be useful to stash a conflicted `git rebase` so I\n> could return to it later and pick up where I left off.  Now we really\n> would need to store some extra metadata, though, like the todo-list\n> and ORIG_HEAD.  And we would definitely need some extra command line\n> switch to tell stash (or rebase) that I want to include all the rebase\n> state and also \"pause\" the rebase by restoring to my starting point.\n\nThis is the sort of thing I'm thinking of, for the \"superstash\" (terrible\nname for it). Note that whatever this becomes, it should be send-able\n(via push and/or email) so that you can have multiple people work\non resolving a particularly hairy merge.\n\nChris\n"},{"id":"418935","messageId":"CABPp-BF9sfqDfj=4885n_xwMr=2=jtOZOACtnPi=QYdC3G-pgQ@mail.gmail.com","threadId":"55291","inReplyTo":"CABURp0pFdHAx_+-e+O35Qxtbe3_+cZy9SZcOSeR2R7v_neRwKg@mail.gmail.com","subject":"Re: [Bug] Stashing during merge loses MERGING state","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2021-03-12T07:02:24Z","receivedAt":"2021-03-12T07:03:40Z","isPatch":false,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Thu, Mar 11, 2021 at 9:21 PM Phil Hord <phil.hord@gmail.com> wrote:\n>\n> On Thu, Mar 11, 2021 at 12:45 PM Tassilo Horn <tsdh@gnu.org> wrote:\n> > >> Or that popping the stash again would also restore the MERGING state.\n> > >\n> > > This would make more sense: the stash records that part of the state,\n> > > and then we make it available again later when the stash is applied.\n> > > However, that feature doesn't exist yet.\n> >\n> > Too bad.\n>\n> Consider also what happens when `git stash apply` results in a merge\n> conflict because of differences between your current index and the one\n> you had when you originally saved the stash.  This results in the\n> usual merge conflict markers that then need to be cleaned up.\n>\n> Could we sanely deal with this in a world where we also tried to\n> restore .git/MERGE_HEAD when the stash was applied. Something like\n> `git stash apply --continue`, possibly after resolving the stash\n> conflicts?  But what if we stashed the merge conflict that resulted\n> from the stash apply?  I guess it would still work, but the stash\n> history would be, um, interesting.\n>\n> I wonder if a fix could be as simple as recording the MERGE_HEAD as\n> the third parent commit of the stash ref. I think that would provide\n> all the information needed to put things back, except possibly for\n> things like the rerere state, which is also set up during a conflict,\n> and other incidentals like .git/MERGE_MSG.  (And it feels like it\n> might break compatibility with older versions that don't expect a\n> third parent.)\n\nThird parent is already reserved by --untracked to store a \"parent\"\ncommit that has all the untracked files added.  So, it'd be a fourth\nparent.  Except when --untracked isn't passed we don't need the third\nparent, and if it wasn't a merge commit we don't need the fourth...fun\ntimes.\n\n> I would be a bit concerned about the possibility of silently creating\n> an \"evil merge\".  Suppose you stash this conflict on some branch and\n> then pop it onto a different one.  I expect we would then be prepared\n> to store all those changes from a different branch including existing\n> resolved merge conflicts into the new one.  That could be surprising\n> and subtle.\n>\n> But maybe I'm overthinking it.  Wouldn't the stash apply result in\n> merge conflicts that would catch out all the troubling parts?\n\nI don't think you're overthinking it; I think this is highly\nproblematic.  Let's consider the following history (from the\ngit-rebase manpage):\n\n               o---o---o---o---o  master\n                    \\\n                     o---o---o---o---o  next\n                                      \\\n                                       o---o---o  topic\n\nFirst, let's consider the case where you don't record MERGE_HEAD when\nstashing.  So, you start out on next and run:\n\n   $ git merge topic\n\nbut you hit some conflicts and stash it:\n\n   $ git stash push -m \"in middle of merging topic\"\n\nNote that this would record applying the changes new to \"topic\" since\n\"next\", with whatever conflicts still exist.  Then sometime later you\ncheck out master, and decide to apply the stash:\n\n   $ git stash apply\n\nWhat would you get?  Just the changes in topic new relative to next,\nbut nothing in next that preceded it.  If you record that as a merge\ncommit with topic as the second parent, you've created an evil merge.\n\n\nOf course, that was saying if you didn't store MERGE_HEAD somewhere.\nBut now let's say you did store MERGE_HEAD (== topic) when you\nstashed.  What then happens when you go to apply the stash?  If you\nreally want a merge with MERGE_HEAD, then you need to redo the merge.\nSo you invoke the merge machinery.  That gives you conflicts anew.\nHow do you use your stash at this point to resolve the set of\nconflicts, even if they were the same as what you got in your original\nmerge?\n\nPersonally, I think we should make stash check for\n$GIT_DIR/MERGE_HEAD, and error out if it exists.  I don't see an easy\nway to make this behave reasonably.  (Which isn't to say I don't see\nways, but it'd probably involve being able to do a diff since the\npoint when the merge stopped and recording it, then attempting to\nreapply _that_ patch, one that removes conflict markers and such, on\ntop of a redone merge, possibly complete with nested conflict markers.\nBut I'm not sure this is sounding like a reasonable level of\ndifficulty for users to deal with.)\n\n> I think being able to stash during a merge conflict could be very\n> useful.  I do sometimes need to get back to a working state\n> momentarily and a merge conflict represents a long pole to doing so.\n> Similarly, it could be useful to stash a conflicted `git rebase` so I\n> could return to it later and pick up where I left off.  Now we really\n> would need to store some extra metadata, though, like the todo-list\n> and ORIG_HEAD.  And we would definitely need some extra command line\n> switch to tell stash (or rebase) that I want to include all the rebase\n> state and also \"pause\" the rebase by restoring to my starting point.\n>\n> Thanks for raising the issue, Tassilo.  This has obviously given me\n> more ideas for things I forgot were missing.\n>\n> > > I can't offhand think of a reason it couldn't be implemented. It's\n> > > possible that it would mess with somebody else's workflow (e.g., they\n> > > think it's useful to stash some changes independent of the merging\n> > > state, and then apply it later, perhaps while replaying the same or a\n> > > similar merge). So it might need to be tied to a command-line option\n> > > or similar.\n> >\n> > Everything breakes someones workflow [1], so an option would be fine.\n> >\n> > However, I'd suggest to protect users shooting in their foot with a\n> > warning and confirmation query for the time being.  I consider myself a\n> > quite experienced git user but this stash trouble today came totally\n> > unexpected.  And I've asked on #git@irc.freenode.net and got no answer\n> > which is totally uncommon.  So I guess that this stash during merge\n> > thing is pretty much a gray area.\n>\n> I don't think we could easily add the warning when the stash is\n> applied since we have forgotten the merge existed in the first place.\n> So we would have to do it during stash save.\n>\n> \"Warning: You are stashing during a merge conflict and your merge\n> state will not be restored by stash apply.\"\n>\n> Seems reasonable.\n\nI think it should be an error and abort the stash operation; this is\nway too much of a footgun.\n"},{"id":"418936","messageId":"CABPp-BERNcL-vx5eZ__Vc6cO2a3Tx4f+HzRPKenERk6mZi7ZDg@mail.gmail.com","threadId":"55291","inReplyTo":"xmqq5z1wc389.fsf@gitster.g","subject":"Re: [Bug] Stashing during merge loses MERGING state","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2021-03-12T07:04:56Z","receivedAt":"2021-03-12T07:05:50Z","isPatch":false,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Thu, Mar 11, 2021 at 10:15 PM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> Phil Hord <phil.hord@gmail.com> writes:\n>\n> > On Thu, Mar 11, 2021 at 12:45 PM Tassilo Horn <tsdh@gnu.org> wrote:\n> >> >> Or that popping the stash again would also restore the MERGING state.\n> >> >\n> >> > This would make more sense: the stash records that part of the state,\n> >> > and then we make it available again later when the stash is applied.\n> >> > However, that feature doesn't exist yet.\n> >>\n> >> Too bad.\n> >\n> > Consider also what happens when `git stash apply` results in a merge\n> > conflict because of differences between your current index and the one\n> > you had when you originally saved the stash.  This results in the\n> > usual merge conflict markers that then need to be cleaned up.\n>\n> I agree with you that allowing a stash while a merge is in progress\n> will introduce many unpleasant corner cases the users wouldn't want\n> to deal with.  We certainly do prevent \"git stash push\" from running\n> when the index is still unmerged (which is a sign that a mergy\n> operation (like pull, rebase, merge, am -3, cherry-pick and revert\n> that stops due to a conflict in the middle) is in progress), but\n> once the end user resolves the conflicts in the index (either\n> manually, or having the rerere.autoupdate feature in effect), such a\n> sign of mergy operation still in progress that \"git stash\" currently\n> uses will be gone.  We should teach \"git stash push\" to pay\n> attention to other such signs like MERGE_HEAD etc. and stop before\n> creating a stash (and also do the same to \"git stash pop/apply\").\n>\n> THanks.\n\nI should have read the rest of the emails before responding.  Once\nagain, you manage to say roughly what I was thinking, but do so both\nmore concisely and more eloquently.\n"},{"id":"418938","messageId":"CABPp-BG=EupfdjZXs5JZu4RPUyv61Rkxf0MQpR2xpGoYk2w6jQ@mail.gmail.com","threadId":"55291","inReplyTo":"CAPx1GvfguSyXznaaeQYB8JY96vmZmzOJyTnXX1yP3omeXptqXw@mail.gmail.com","subject":"Re: [Bug] Stashing during merge loses MERGING state","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2021-03-12T07:17:04Z","receivedAt":"2021-03-12T07:18:22Z","isPatch":false,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Thu, Mar 11, 2021 at 11:07 PM Chris Torek <chris.torek@gmail.com> wrote:\n>\n> On Thu, Mar 11, 2021 at 9:19 PM Phil Hord <phil.hord@gmail.com> wrote:\n> > I wonder if a fix could be as simple as recording the MERGE_HEAD as\n> > the third parent commit of the stash ref.\n>\n> There is already a third parent, but only when using -u / -a: this\n> third-parent commit holds the untracked files (which are then removed\n> a la `git clean`).\n>\n> A better trick would, I think, be able to save a partial merge state\n> in general, including the unmerged statuses of various files, the\n> ongoing action (merge or one of the other things that use it), and\n> so on, in a form that could be restored later.  A plain `git stash` in\n> any partially-merged state should tell you: no, use the fancier\n> merge-state-saver instead.\n>\n> > I think being able to stash during a merge conflict could be very\n> > useful.  I do sometimes need to get back to a working state\n> > momentarily and a merge conflict represents a long pole to doing so.\n> > Similarly, it could be useful to stash a conflicted `git rebase` so I\n> > could return to it later and pick up where I left off.  Now we really\n> > would need to store some extra metadata, though, like the todo-list\n> > and ORIG_HEAD.  And we would definitely need some extra command line\n> > switch to tell stash (or rebase) that I want to include all the rebase\n> > state and also \"pause\" the rebase by restoring to my starting point.\n>\n> This is the sort of thing I'm thinking of, for the \"superstash\" (terrible\n> name for it). Note that whatever this becomes, it should be send-able\n> (via push and/or email) so that you can have multiple people work\n> on resolving a particularly hairy merge.\n\nYou can use git-imerge (https://github.com/mhagger/git-imerge) for\nthat...just not once you've already started a merge (unless you're\nwilling to undo and restart).\n\nAs per my other email, I'm pretty worried about attempting to stash a\nmerge, given that stash allows its contents to be \"reapplied\" on top\nof a different commit.  That works fine for single-parent commits, but\nmerges have multiple parents and it'd be rather tricky to reapply such\na stash on a different base without creating an evil merge.  Perhaps\nif \"superstash\" forced you to only reapply on the same base then it'd\nbe fine...but it's starting to no longer be a \"stash\" anymore but\nsomething else.\n"}]}