{"thread":{"id":"57947","subject":"Introduce \"git stash --continue\" and \"git stash --abort\"?","startedAt":"2022-06-02T16:40:27Z","lastAt":"2022-06-03T08:30:05Z","messageCount":3,"participants":["Tao Klerks","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"456528","messageId":"CAPMMpohvKSgcL=X=Z=Wf7zHRr_Ghex5oZ4iUTgZL7XhHSWFi8g@mail.gmail.com","threadId":"57947","inReplyTo":null,"subject":"Introduce \"git stash --continue\" and \"git stash --abort\"?","fromName":"Tao Klerks","fromEmail":"tao@klerks.biz","sentAt":"2022-06-02T16:40:09Z","receivedAt":"2022-06-02T16:40:27Z","isPatch":false,"sender":{"key":"tao@klerks.biz","avatar":"https://avatars.githubusercontent.com/u/531704?v=4"},"body":"Hi folks,\n\nI've spent a little time trying to understand how git stash behaves,\nand understanding the differences wrt how a \"naive user\" (eg me?)\nwould expect it to.\n\nSo far most of the differences are about defaults, eg:\n* I would expect \"git stash push\" (or \"git stash\") to\n\"--include-untracked\" by default\n* I would expect \"git stash pop\" to include \"--index\" by default\n* I would expect \"git checkout\" (or at least \"git switch\") to have an\n\"--autostash\" option like \"git rebase\" and \"git merge\" do\n\nThere's one \"bigger\" thing though, that sounds like a whole project:\nThe behavior of \"stash pop\" in the case of conflicts is somewhat\ntraumatizing:\n\n* My worktree is left in a \"conflicted\" state, and the only way to\n\"back out\" seems to be some sort of \"reset\" (but good luck figuring\nout which one, or how to revert the stash-based changes without\nimpacting any other uncommitted changes that I had in my worktree)\n\n* If I \"forge on\", resolve the conflicts, and stage the conflicted\nfiles... my stash stack still contains something that I didn't intend\nit to, until/unless I remember to \"git stash drop\"... which is an\nunsafe (non-idempotent / not-easily-reversible) operation...\n\nI would expect that some sort of merge- or rebase-like \"--continue or\n--abort\" facility would make this much easier to understand... but of\ncourse I have no idea how one would go about doing that. I assume the\nclosest existing pattern would be \"git cherry-pick\", but I imagine I'm\nmissing lots of subtleties.\n\nI understand Brian M. Carlson has been working on big changes around\nstash export, and Victoria Dye has been working on Sparse Index\nsupport, but I'm not aware of any other major ongoing work from\nskimming the mailing list in the past months.\n\nIs this kind of direction one that's been considered before? Are there\nreasons why it's a bad idea?\n\nThanks,\nTao\n"},{"id":"456537","messageId":"xmqq5ylior3l.fsf@gitster.g","threadId":"57947","inReplyTo":"CAPMMpohvKSgcL=X=Z=Wf7zHRr_Ghex5oZ4iUTgZL7XhHSWFi8g@mail.gmail.com","subject":"Re: Introduce \"git stash --continue\" and \"git stash --abort\"?","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2022-06-02T18:30:38Z","receivedAt":"2022-06-02T18:30:46Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Tao Klerks <tao@klerks.biz> writes:\n\n> I would expect that some sort of merge- or rebase-like \"--continue or\n> --abort\" facility would make this much easier to understand... but of\n> course I have no idea how one would go about doing that. I assume the\n> closest existing pattern would be \"git cherry-pick\", but I imagine I'm\n> missing lots of subtleties.\n> ...\n> Is this kind of direction one that's been considered before? Are there\n> reasons why it's a bad idea?\n\nI saw a few exchange on the intended use of \"stash\" on another\nthread in the past days, but I think the reason why the current\nset of defaults and behaviour are appropriate for \"stash\" is related\nto it.\n\nThe intended use of \"stash\" is to clear the deck as quickly as\npossible to deal with \"emergencies\", and its behaviour comes from\nthe need to support that use case effectively.  Untracked cruft are\noften useful even when you do a \"quick context switch\" (aka \"the\nboss suddenly appears and asks you to do something different real\nquick\"), hence \"-u\" is not the default, for example.  \"stash pop\"\nwas the primary way to go back to where you were before the\ninterruption, and such going back is expected to be done after the\ncrisis is over when you can be more relaxed, and was expected to be\ndone _after_ you \"reset --hard\" and/or \"git switch\" out of the\ncrisis mode.  And the natural way to recover from \"eh, I moved back\nto a different commit---I wanted to go to the commit I was when I\nsaved the stash\" was \"reset --hard\" that would not lose anything new\n(and \"stash branch\" was later added to make the last one easier to\ndo), for another example.\n\nUsers are better off doing any large scale \"I made a mess in the\nworking tree with mixed changes, and I want to take time to separate\nthem out\" on separate (possibly temporary) branches, instead of\nusing \"stash save\" + \"stash pop\".  Any change that would make it\nmore cumbersome for the primary intended purpose of \"quick save\"\nwould be very much unwelcome, I would have to say.\n\nThanks.\n\n"},{"id":"456552","messageId":"CAPMMpojDoyJ+prLHKATnH2rVBVX=x0ES__6rvAZyq7GNiwutHw@mail.gmail.com","threadId":"57947","inReplyTo":"xmqq5ylior3l.fsf@gitster.g","subject":"Re: Introduce \"git stash --continue\" and \"git stash --abort\"?","fromName":"Tao Klerks","fromEmail":"tao@klerks.biz","sentAt":"2022-06-03T08:29:45Z","receivedAt":"2022-06-03T08:30:05Z","isPatch":false,"sender":{"key":"tao@klerks.biz","avatar":"https://avatars.githubusercontent.com/u/531704?v=4"},"body":"On Thu, Jun 2, 2022 at 8:30 PM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> Tao Klerks <tao@klerks.biz> writes:\n>\n> > I would expect that some sort of merge- or rebase-like \"--continue or\n> > --abort\" facility would make this much easier to understand... but of\n> > course I have no idea how one would go about doing that. I assume the\n> > closest existing pattern would be \"git cherry-pick\", but I imagine I'm\n> > missing lots of subtleties.\n> > ...\n> > Is this kind of direction one that's been considered before? Are there\n> > reasons why it's a bad idea?\n>\n> I saw a few exchange on the intended use of \"stash\" on another\n> thread in the past days, but I think the reason why the current\n> set of defaults and behaviour are appropriate for \"stash\" is related\n> to it.\n>\n> The intended use of \"stash\" is to clear the deck as quickly as\n> possible to deal with \"emergencies\", and its behaviour comes from\n> the need to support that use case effectively.\n\nMakes sense, with you so far!\n\n> Untracked cruft are\n> often useful even when you do a \"quick context switch\" (aka \"the\n> boss suddenly appears and asks you to do something different real\n> quick\"), hence \"-u\" is not the default, for example.\n\nI don't understand this statement - I would argue the exact opposite\nis true in all the day-to-day usage of git that I have come across.\n\nWhen I have an untracked file in my working tree, it's normally\nbecause I've created a new script, a new java class, or something like\nthat. It's normally part of what I'm working on - eg I added a file,\nand another might well be referencing it.\n\nIf I have \"untracked cruft\" that doesn't logically belong in my\nworking code / shouldn't be checked in / doesn't affect the\ncompilability of my project, then I would typically consider this a\nbug in my workflow - either there's a pattern missing in my\n\".gitignore\", or I accidentally redirected some command output into a\ntemp file in my working folder instead of a more sensible place. I\nunderstand a large segment of the *test suite* relies on git's\n\"untracked files don't get in the way\" behavior, but I don't think\nthat's representative of real-world usage.\n\nObviously this is a \"personal\" thing, but it seems to me that git\nwould benefit from supporting this worldview - *allowing* stash to\ndefault to -u, and similarly allowing \"git commit -a\" to refer to\nuntracked files also, which it does not today.\n\nAnyway, sorry, I'm reacting to the perspective and statement about the\nrole of untracked files in git working trees here, rather than\nanything specific about stashes, I guess this is off-topic.\n\n> \"stash pop\"\n> was the primary way to go back to where you were before the\n> interruption, and such going back is expected to be done after the\n> crisis is over when you can be more relaxed, and was expected to be\n> done _after_ you \"reset --hard\" and/or \"git switch\" out of the\n> crisis mode.\n\nYep, makes sense - except this perspective is at odds of course with\nthe stashes being a stack, and with the idea of attempting to export\nstashes at all. I understand these are the *primary* usecases, and\nthose that need to be best-served, absolutely.\n\n> And the natural way to recover from \"eh, I moved back\n> to a different commit---I wanted to go to the commit I was when I\n> saved the stash\" was \"reset --hard\" that would not lose anything new\n> (and \"stash branch\" was later added to make the last one easier to\n> do), for another example.\n\nThis explains why stash was implemented to behave the way it does,\nsure - it made narrow assumptions about the likely context in which a\nstash would be popped; my concern with that is that it does not\nenforce those assumptions, so its actual usage in the wild might well\ndiffer significantly from those assumptions, and *when* it does, it\ncan leave your working tree in a messed up state (a mix of staged and\nunstaged changes that had nothing to do with the stash, some staged or\nunstaged changes successfully \"popped\" and some stash-popped conflicts\nthat you cannot easily \"undo\" without carefully picking apart the\nstash-popped bits from the previously present bits).\n\n>\n> Users are better off doing any large scale \"I made a mess in the\n> working tree with mixed changes, and I want to take time to separate\n> them out\" on separate (possibly temporary) branches, instead of\n> using \"stash save\" + \"stash pop\".\n\nI agree with this, especially given that stash pop doesn't give you\nany opportunity to \"partially pop\".\n\nIn the usecase that I describe (where you \"stash pop\" into a working\ntree that *already* has unrelated staged or unstaged changes), the\nintention is not to use stash to help resolve a mess you made - it's\njust to \"bring back\" that stuff you stashed earlier. Stash pop isn't\nbeing used to fix anything - it is accidentally *creating* a problem\nif/when the stash pop encounters conflicts. It is this problem that I\nbelieve could be solved with an --abort/--continue model for stash\nconflicts.\n\n> Any change that would make it\n> more cumbersome for the primary intended purpose of \"quick save\"\n> would be very much unwelcome, I would have to say.\n\nThat makes complete sense, I agree!\n\nI believe introducing --abort/--continue on *conflictive*\nstash-popping would absolutely not make those intended uses any more\ncumbersome - if anything, it would make them much cleaner/smoother\nwith a simpler, more consistent and safer \"exit\" from the conflict in\neither direction: if the conflict is resolved, \"stash --continue\" will\ndrop the stash without risk of dropping anything else you had in the\nstash. If you reconsider, \"stash --abort\" gets you back to where you\nwere, without having to think about how safe or dangerous the\noperation might be.\n\nIt might well not be worthwhile, because stash is so hard to use at\nthe moment that the standing advice I see around is \"don't do it -\nyou're better off learning how to manage branches and commits in a\nsufficiently agile fashion that you never worry about stash, and just\ncreate & drop local branches instead\". If stash is rarely used, or\nonly used by people who already know exactly when it works well and\navoid using it in situations where it causes problems, then it might\nnot be worth investing in. However, if stash is to graduate to a\nsimple to use and reasonably safe facility, then I would expect this\nto make sense from a functional perspective.\n\nOn the other hand, I understand that each --abort/--continue\nconflict-management flow probably requires/implies another\nspecial/dedicated \"working tree state\" that tools (eg git-prompt), git\ncommands, third-party git libraries, and GUI clients need to know\nabout, so I'm guessing the overhead on something like this is\nprohibitive? When was the last time something like this was done?\n\nThanks,\nTao\n"}]}