{"thread":{"id":"17897","subject":"git merge --abort","startedAt":"2009-02-19T10:05:57Z","lastAt":"2009-02-24T09:51:41Z","messageCount":18,"participants":["John Tapsell","Junio C Hamano","Jay Soffian","Bryan Donlan","Jakub Narebski"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"105425","messageId":"43d8ce650902190205yc2274c5gb8e658c8608267ff@mail.gmail.com","threadId":"17897","inReplyTo":null,"subject":"git merge --abort","fromName":"John Tapsell","fromEmail":"johnflux@gmail.com","sentAt":"2009-02-19T10:05:57Z","receivedAt":"2009-02-19T10:05:57Z","isPatch":false,"sender":{"key":"johnflux@gmail.com","avatar":"https://gravatar.com/avatar/25f70d4c0f96396b84a2e34bcd9bdc233462c7b4be29b5fdca8266fc53f30b0c?d=mp&s=160"},"body":"Hi,\n\n I hope you don't mind me generating lots of noise here..\n\n  It's not obvious how to abort a merge between two trees.  Would\naliasing  \"git merge --abort\"  to \"git reset --hard\"  be sensible?  Is\nthere a better way to abort a merge?  Especially if you have\nuncommitted changes.\n\n  If that idea isn't liked, instead maybe we can add a note to 'git\nmerge --help' on how to abort.\n\nJohn\n"},{"id":"105436","messageId":"7v63j6n16s.fsf@gitster.siamese.dyndns.org","threadId":"17897","inReplyTo":"43d8ce650902190205yc2274c5gb8e658c8608267ff@mail.gmail.com","subject":"Re: git merge --abort","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-02-19T10:58:03Z","receivedAt":"2009-02-19T10:58:03Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"John Tapsell <johnflux@gmail.com> writes:\n\n>   It's not obvious how to abort a merge between two trees.  Would\n> aliasing  \"git merge --abort\"  to \"git reset --hard\"  be sensible?\n\nNot at all.  Especially when you have local changes.\n\nThere are two classes of users who would get themselves into a conflicted\nmerge while they have local changes.  One is people who know what they are\ndoing (like Linus) run \"git pull\" while having small set of disposable\nlocal changes they do not mind losing, and they know how to recover.  The\nother is recent CVS/SVN migrants who learned (incorrectly) that \"git pull\"\nis similar to \"cvs update\" from wrong sources that say \"it is a way to get\nchanges made by other people while you have a half-baked mess that is\nstill not ready to be committed in your work tree\" (which is not) [*1*].\n\n\"git reset --hard\" is the last thing you would want to suggest to the\nlatter class of people.\n\nImmediately after a merge result in conflicts, there should be two kinds\nof paths that are different from HEAD:\n\n * The ones you had local modifications before you started the failed\n   merge.  They should be left intact after \"merge --abort\".\n\n * The ones you did not have local modifications, but merge could not\n   automatically resolve.  There may be files with conflicted marker in\n   the work tree, or there may be not.\n\nIf you had local modifications to a path that would be involved in the\nmerge, the merge *ought to* stop before even touching the index nor the\nwork tree [*2*].  Merge would not start if you had any staged changes in\nthe index.  So the recovery strategy for \"merge --abort\" needs to only\nworry about the above two cases.  The correct implementation would be\nroughly:\n\n - If the index does not have any unmerged entries, stop.  The merge did\n   not do anything, and there is nothing to abort.\n\n - For each path that has unmerged entries in the index:\n\n   - If the path does not exist in HEAD, drop the unmerged index entries\n     for the path, without touching the work tree (if a file exists there,\n     it must have existed as an untracked file before the merge started);\n\n   - If the path does exist in HEAD, discard the unmerged index entries, \n     reset the path in the index from HEAD, and write that out to the work\n     tree.\n\n - For each path whose entry is stage #0 in the index, if it is different\n   from HEAD:\n\n   - If it does not exist in HEAD, drop it from the index and remove the\n     file from the work tree.  It is a file added by the failed merge and\n     couldn't have existed as an untracked file before the merge started.\n\n   - If it does exist in HEAD, reset the path in the index from HEAD, and\n     write that out to the work tree.\n\nBut the above would be correct *only* immediately after a failed merge.\nThe user could be giving up after having done any random things after a\nfailed merge in an attempt to resolve, and at that point we cannot trust\nthe state of the index nor the work tree.  The simplest example to\nillustrate:\n\n    $ edit goodbye.c ;# without \"git add\"\n    $ git merge other\n    Conflict in hello.c\n    $ git add goodbye.c\n    $ git merge --abort ;# ???\n\nThe user's \"git add goodbye.c\" will make the state of the index unusable\nfor the above outlined algorithm to tell what was changed by the merge and\nwhat were already different before the merge.\n\nSo in general, even \"merge --abort\" implemented according to the above\noutline cannot be sold as \"a safe procedure to recover to where you were\nbefore you started the last failed merge\".  There is no such thing, unless\nyou really educate the user not to expect miracle.\n\nIf you mistakenly run \"git merge\" while your index is already unmerged\n(iow, after a failed merge before you resolved it nor resetted the index),\nthe command aborts without touching the index nor the work tree.  If you\nimplement \"merge --abort\" as outlined above, it will try to abort the\nprevious conflicted merge, not this round which did not do anything, but\nagain, the user could have done any other random things in addition to the\nattempt to run the second \"git merge\".\n\nHaving said all that, I suspect\n\n\t$ git reset --merge HEAD\n\nmay do the right thing, if your git already has the option ;-)\n\n\n[Footnote]\n\n*1* CVS/SVN want to linearize so even if your local changes want to go\ndirecty on top of what you checked out, \"cvs update\" tries to replay your\nuncommitted changes on top of what comes as the latest from the central\nserver, which could result in conflicts.  With git, you do not have to\nrisk losing your local changes that way.  Instead, you can commit your\nlocal changes and then \"git pull\" will try to merge.  The merge can\nconflict and leave the same mess as \"cvs update\" would leave when it tries\nto replay your uncommitted changes, but a _huge_ difference here is that\nyou get only one chance to resolve that conflict with CVS/SVN (because\nnothing records your local changes before the \"update\") and if you screw\nthat up, you are out of luck.  With git, you have the local commit that\nrecords the changes you did on top of the old tip of the branch, and you\ncan redo the merge.\n\n*2* I say *ought to*, and I am reasonably sure resolve strategy works\ncorrectly, but I wouldn't be surprised if recursive strategy which is the\ndefault these days still have corner case bugs when the merge involves\nrenames and/or D/F conflicts).\n"},{"id":"105460","messageId":"43d8ce650902190534j49e24f86k9b716190ae3d134b@mail.gmail.com","threadId":"17897","inReplyTo":"7v63j6n16s.fsf@gitster.siamese.dyndns.org","subject":"Re: git merge --abort","fromName":"John Tapsell","fromEmail":"johnflux@gmail.com","sentAt":"2009-02-19T13:34:03Z","receivedAt":"2009-02-19T13:34:03Z","isPatch":false,"sender":{"key":"johnflux@gmail.com","avatar":"https://gravatar.com/avatar/25f70d4c0f96396b84a2e34bcd9bdc233462c7b4be29b5fdca8266fc53f30b0c?d=mp&s=160"},"body":"2009/2/19 Junio C Hamano <gitster@pobox.com>:\n> John Tapsell <johnflux@gmail.com> writes:\n>\n>>   It's not obvious how to abort a merge between two trees.  Would\n>> aliasing  \"git merge --abort\"  to \"git reset --hard\"  be sensible?\n>\n> Not at all.  Especially when you have local changes.\n\nJust to confirm that I've understood this - there's currently no way\nat the moment to 'cancel' an abort.  In the example you gave:\n\n>    $ edit goodbye.c ;# without \"git add\"\n>    $ git merge other\n>    Conflict in hello.c\n>    $ git add goodbye.c\n>    $ git merge --abort ;# ???\n\nThere's no reliable way of getting back to the state before the merge?\n\n\n> The user's \"git add goodbye.c\" will make the state of the index unusable\n> for the above outlined algorithm to tell what was changed by the merge and\n> what were already different before the merge.\n>\n> So in general, even \"merge --abort\" implemented according to the above\n> outline cannot be sold as \"a safe procedure to recover to where you were\n> before you started the last failed merge\".  There is no such thing, unless\n> you really educate the user not to expect miracle.\n>\n> If you mistakenly run \"git merge\" while your index is already unmerged\n> (iow, after a failed merge before you resolved it nor resetted the index),\n> the command aborts without touching the index nor the work tree.  If you\n> implement \"merge --abort\" as outlined above, it will try to abort the\n> previous conflicted merge, not this round which did not do anything, but\n> again, the user could have done any other random things in addition to the\n> attempt to run the second \"git merge\".\n>\n> Having said all that, I suspect\n>\n>        $ git reset --merge HEAD\n>\n> may do the right thing, if your git already has the option ;-)\n>\n>\n> [Footnote]\n>\n> *1* CVS/SVN want to linearize so even if your local changes want to go\n> directy on top of what you checked out, \"cvs update\" tries to replay your\n> uncommitted changes on top of what comes as the latest from the central\n> server, which could result in conflicts.  With git, you do not have to\n> risk losing your local changes that way.  Instead, you can commit your\n> local changes and then \"git pull\" will try to merge.  The merge can\n> conflict and leave the same mess as \"cvs update\" would leave when it tries\n> to replay your uncommitted changes, but a _huge_ difference here is that\n> you get only one chance to resolve that conflict with CVS/SVN (because\n> nothing records your local changes before the \"update\") and if you screw\n> that up, you are out of luck.  With git, you have the local commit that\n> records the changes you did on top of the old tip of the branch, and you\n> can redo the merge.\n>\n> *2* I say *ought to*, and I am reasonably sure resolve strategy works\n> correctly, but I wouldn't be surprised if recursive strategy which is the\n> default these days still have corner case bugs when the merge involves\n> renames and/or D/F conflicts).\n>\n"},{"id":"105510","messageId":"76718490902191226k7b87f478p9a79b9b2372b464d@mail.gmail.com","threadId":"17897","inReplyTo":"43d8ce650902190534j49e24f86k9b716190ae3d134b@mail.gmail.com","subject":"Re: git merge --abort","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2009-02-19T20:26:48Z","receivedAt":"2009-02-19T20:26:48Z","isPatch":false,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"On Thu, Feb 19, 2009 at 8:34 AM, John Tapsell <johnflux@gmail.com> wrote:\n> There's no reliable way of getting back to the state before the merge?\n\nSure there is. Commit or stash before you merge, so that your index\nand working copy are clean.\n\nj.\n"},{"id":"105553","messageId":"43d8ce650902192047g383a5cc1re6697e8009ad72fc@mail.gmail.com","threadId":"17897","inReplyTo":"76718490902191226k7b87f478p9a79b9b2372b464d@mail.gmail.com","subject":"Re: git merge --abort","fromName":"John Tapsell","fromEmail":"johnflux@gmail.com","sentAt":"2009-02-20T04:47:39Z","receivedAt":"2009-02-20T04:47:39Z","isPatch":false,"sender":{"key":"johnflux@gmail.com","avatar":"https://gravatar.com/avatar/25f70d4c0f96396b84a2e34bcd9bdc233462c7b4be29b5fdca8266fc53f30b0c?d=mp&s=160"},"body":"2009/2/19 Jay Soffian <jaysoffian@gmail.com>:\n> On Thu, Feb 19, 2009 at 8:34 AM, John Tapsell <johnflux@gmail.com> wrote:\n>> There's no reliable way of getting back to the state before the merge?\n>\n> Sure there is. Commit or stash before you merge, so that your index\n> and working copy are clean.\n\nCould a stash be done automatically by the merge command, for just a case?\n\nJohn\n"},{"id":"105561","messageId":"7v7i3lk7dp.fsf@gitster.siamese.dyndns.org","threadId":"17897","inReplyTo":"43d8ce650902192047g383a5cc1re6697e8009ad72fc@mail.gmail.com","subject":"Re: git merge --abort","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-02-20T05:24:49Z","receivedAt":"2009-02-20T05:24:49Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"John Tapsell <johnflux@gmail.com> writes:\n\n> 2009/2/19 Jay Soffian <jaysoffian@gmail.com>:\n>> On Thu, Feb 19, 2009 at 8:34 AM, John Tapsell <johnflux@gmail.com> wrote:\n>>> There's no reliable way of getting back to the state before the merge?\n>>\n>> Sure there is. Commit or stash before you merge, so that your index\n>> and working copy are clean.\n>\n> Could a stash be done automatically by the merge command, for just a case?\n\nIt cuts both ways.  For people who work on a well organized project\n(i.e. highly modularized) and tend to keep local changes in the work tree\nwhile doing a lot of merges, running \"stash\" every time would (1) remove\nthe local change from the work tree, which he has to remember to manually\nunstash after resolving conflicts in the merge (which would not have\nconflicted with the local change anyway), which is an additional work for\nno real gain, and (2) clutter his stash.  My gut feeling is that it is a\nchange that affects the way the end user has to work that is sufficiently\ndifferent and disruptive for no real gain.\n\nIf you read the original message more carefully, you will notice that the\nsuggested \"git merge --abort\" would break down *only* if the user messes\nwith the state conflicted merge left.  And an unmanageable conflicts are\nmuch rare compared to most merges that autoresolve, so you should optimze\nfor the common case while giving a way to gain safety only when needed.\n\nProbably a much better workflow, if we add \"merge --abort\", would be:\n\n    $ edit ;# unrelated local changes are still here\n    $ git pull ;# or merge or whatever\n    ... oops, large conflict ...\n    ... look and see if it can easily be resolved ...\n    ... otherwise\n    $ git merge --abort\n    $ git stash\n    $ git pull ;# or whatever, try again\n    ... the same conflict but this time you only need to worry\n    ... about the merge itself\n    ... resolve, review, test to convince yourself that your\n    ... resolution is good and then...\n    $ git commit\n    $ git stash pop\n"},{"id":"105577","messageId":"43d8ce650902200013q4aca6b2na27092e0825f969a@mail.gmail.com","threadId":"17897","inReplyTo":"7v7i3lk7dp.fsf@gitster.siamese.dyndns.org","subject":"Re: git merge --abort","fromName":"John Tapsell","fromEmail":"johnflux@gmail.com","sentAt":"2009-02-20T08:13:46Z","receivedAt":"2009-02-20T08:13:46Z","isPatch":false,"sender":{"key":"johnflux@gmail.com","avatar":"https://gravatar.com/avatar/25f70d4c0f96396b84a2e34bcd9bdc233462c7b4be29b5fdca8266fc53f30b0c?d=mp&s=160"},"body":"2009/2/20 Junio C Hamano <gitster@pobox.com>:\n<snip>\n>    $ edit ;# unrelated local changes are still here\n>    $ git pull ;# or merge or whatever\n>    ... oops, large conflict ...\n>    ... look and see if it can easily be resolved ...\n>    ... otherwise\n>    $ git merge --abort\n\nCan I just confirm - at this stage, \"git merge --abort\" would be a\n\"git reset --hard HEAD\" ?\n\nSo could \"git pull/merge\" detect if there were local changes, and if\nthere are tell the user something along the lines that they have to\neither abort the merge, or be unable to abort later?\n\n>    $ git stash\n>    $ git pull ;# or whatever, try again\n>    ... the same conflict but this time you only need to worry\n>    ... about the merge itself\n>    ... resolve, review, test to convince yourself that your\n>    ... resolution is good and then...\n>    $ git commit\n>    $ git stash pop\n"},{"id":"105580","messageId":"7vljs1fqxn.fsf@gitster.siamese.dyndns.org","threadId":"17897","inReplyTo":"43d8ce650902200013q4aca6b2na27092e0825f969a@mail.gmail.com","subject":"Re: git merge --abort","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-02-20T08:33:40Z","receivedAt":"2009-02-20T08:33:40Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"John Tapsell <johnflux@gmail.com> writes:\n\n> 2009/2/20 Junio C Hamano <gitster@pobox.com>:\n> <snip>\n>>    $ edit ;# unrelated local changes are still here\n>>    $ git pull ;# or merge or whatever\n>>    ... oops, large conflict ...\n>>    ... look and see if it can easily be resolved ...\n>>    ... otherwise\n>>    $ git merge --abort\n>\n> Can I just confirm - at this stage, \"git merge --abort\" would be a\n> \"git reset --hard HEAD\" ?\n\nNot at all.  Please re-read my previous message that begins with \"Not at\nall\".\n"},{"id":"105585","messageId":"43d8ce650902200042y13caa60dtcc55d8069d90ee4d@mail.gmail.com","threadId":"17897","inReplyTo":"7vljs1fqxn.fsf@gitster.siamese.dyndns.org","subject":"Re: git merge --abort","fromName":"John Tapsell","fromEmail":"johnflux@gmail.com","sentAt":"2009-02-20T08:42:34Z","receivedAt":"2009-02-20T08:42:34Z","isPatch":false,"sender":{"key":"johnflux@gmail.com","avatar":"https://gravatar.com/avatar/25f70d4c0f96396b84a2e34bcd9bdc233462c7b4be29b5fdca8266fc53f30b0c?d=mp&s=160"},"body":"2009/2/20 Junio C Hamano <gitster@pobox.com>:\n> John Tapsell <johnflux@gmail.com> writes:\n>\n>> 2009/2/20 Junio C Hamano <gitster@pobox.com>:\n>> <snip>\n>>>    $ edit ;# unrelated local changes are still here\n>>>    $ git pull ;# or merge or whatever\n>>>    ... oops, large conflict ...\n>>>    ... look and see if it can easily be resolved ...\n>>>    ... otherwise\n>>>    $ git merge --abort\n>>\n>> Can I just confirm - at this stage, \"git merge --abort\" would be a\n>> \"git reset --hard HEAD\" ?\n>\n> Not at all.  Please re-read my previous message that begins with \"Not at all\".\n\nDoh sorry.  Yeah it has to be that long algorithm that you outlined.\nCan it be done with a series of currently existing commands?  Can I\npersuade someone else to implement it ? :-)\n\nJohn\n"},{"id":"105693","messageId":"3e8340490902202328r7caca98q973c17dc163e2028@mail.gmail.com","threadId":"17897","inReplyTo":"7v7i3lk7dp.fsf@gitster.siamese.dyndns.org","subject":"Re: git merge --abort","fromName":"Bryan Donlan","fromEmail":"bdonlan@gmail.com","sentAt":"2009-02-21T07:28:27Z","receivedAt":"2009-02-21T07:28:27Z","isPatch":false,"sender":{"key":"bdonlan@gmail.com","avatar":null},"body":"On Fri, Feb 20, 2009 at 12:24 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> John Tapsell <johnflux@gmail.com> writes:\n>\n>> 2009/2/19 Jay Soffian <jaysoffian@gmail.com>:\n>>> On Thu, Feb 19, 2009 at 8:34 AM, John Tapsell <johnflux@gmail.com> wrote:\n>>>> There's no reliable way of getting back to the state before the merge?\n>>>\n>>> Sure there is. Commit or stash before you merge, so that your index\n>>> and working copy are clean.\n>>\n>> Could a stash be done automatically by the merge command, for just a case?\n>\n> It cuts both ways.  For people who work on a well organized project\n> (i.e. highly modularized) and tend to keep local changes in the work tree\n> while doing a lot of merges, running \"stash\" every time would (1) remove\n> the local change from the work tree, which he has to remember to manually\n> unstash after resolving conflicts in the merge (which would not have\n> conflicted with the local change anyway), which is an additional work for\n> no real gain, and (2) clutter his stash.  My gut feeling is that it is a\n> change that affects the way the end user has to work that is sufficiently\n> different and disruptive for no real gain.\n\nPerhaps a better approach would be to stash the pre-merge state in the\nreflog, then? That is, manufacture a pre-merge commit containing all\nfiles changed in the working copy, and add it to the reflog prior to\nperforming a merge. git merge --abort can then simply check whether\nthe top reflog entry is a pre-merge state, and if so, reset --hard to\nit, then reset the index to the parent of our pre-merge commit.\n\nThis would also nicely handle the case where the user tries some\nrandom things before deciding to abort the merge.\n"},{"id":"105695","messageId":"m3ocwwrxtg.fsf@localhost.localdomain","threadId":"17897","inReplyTo":"3e8340490902202328r7caca98q973c17dc163e2028@mail.gmail.com","subject":"Re: git merge --abort","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2009-02-21T08:34:58Z","receivedAt":"2009-02-21T08:34:58Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Bryan Donlan <bdonlan@gmail.com> writes:\n> On Fri, Feb 20, 2009 at 12:24 AM, Junio C Hamano <gitster@pobox.com> wrote:\n>> John Tapsell <johnflux@gmail.com> writes:\n>>> 2009/2/19 Jay Soffian <jaysoffian@gmail.com>:\n>>>> On Thu, Feb 19, 2009 at 8:34 AM, John Tapsell <johnflux@gmail.com> wrote:\n>>>>>\n>>>>> There's no reliable way of getting back to the state before the merge?\n>>>>\n>>>> Sure there is. Commit or stash before you merge, so that your index\n>>>> and working copy are clean.\n>>>\n>>> Could a stash be done automatically by the merge command, for just a case?\n>>\n>> It cuts both ways.  For people who work on a well organized project\n>> (i.e. highly modularized) and tend to keep local changes in the work tree\n>> while doing a lot of merges, running \"stash\" every time would (1) remove\n>> the local change from the work tree, which he has to remember to manually\n>> unstash after resolving conflicts in the merge (which would not have\n>> conflicted with the local change anyway), which is an additional work for\n>> no real gain, and (2) clutter his stash.  My gut feeling is that it is a\n>> change that affects the way the end user has to work that is sufficiently\n>> different and disruptive for no real gain.\n> \n> Perhaps a better approach would be to stash the pre-merge state in the\n> reflog, then? That is, manufacture a pre-merge commit containing all\n> files changed in the working copy, and add it to the reflog prior to\n> performing a merge. git merge --abort can then simply check whether\n> the top reflog entry is a pre-merge state, and if so, reset --hard to\n> it, then reset the index to the parent of our pre-merge commit.\n> \n> This would also nicely handle the case where the user tries some\n> random things before deciding to abort the merge.\n\nPerhaps this is the case fo \"feature that waits for a user\", namely\n'git stash --no-reset', which would save a state just in case, perhaps\nin a separate area and not refs/stash (ORIG_STASH perhaps?).\n\nWhat do you think about this idea?\n-- \nJakub Narebski\nPoland\nShadeHawk on #git\n"},{"id":"105696","messageId":"7v3ae8rvvd.fsf@gitster.siamese.dyndns.org","threadId":"17897","inReplyTo":"m3ocwwrxtg.fsf@localhost.localdomain","subject":"Re: git merge --abort","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-02-21T09:18:30Z","receivedAt":"2009-02-21T09:18:30Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jakub Narebski <jnareb@gmail.com> writes:\n\n> Perhaps this is the case fo \"feature that waits for a user\", namely\n> 'git stash --no-reset', which would save a state just in case, perhaps\n> in a separate area and not refs/stash (ORIG_STASH perhaps?).\n\nIsn't that Nana's \"git stash --keep\" patch posted a few weeks ago sitting\nin \"pu\"?\n"},{"id":"105699","messageId":"200902211118.32185.jnareb@gmail.com","threadId":"17897","inReplyTo":"7v3ae8rvvd.fsf@gitster.siamese.dyndns.org","subject":"Re: git merge --abort","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2009-02-21T10:18:30Z","receivedAt":"2009-02-21T10:18:30Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"On Sat, 21 Feb 2009, Junio C Hamano wrote:\n> Jakub Narebski <jnareb@gmail.com> writes:\n> \n> > Perhaps this is the case fo \"feature that waits for a user\", namely\n> > 'git stash --no-reset', which would save a state just in case, perhaps\n> > in a separate area and not refs/stash (ORIG_STASH perhaps?).\n> \n> Isn't that Nana's \"git stash --keep\" patch posted a few weeks ago sitting\n> in \"pu\"?\n\nAlmost exactly.\n\nWhen using it as a safety measure (perhaps enabled via configuration\nvariable, similarly to core.safecrlf or diff.autoRefreshIndex) we would\nprobably want to not save it in 'refs/stash' stack, but in single-use\nORIG_STATE (similar to HEAD reflog vs. ORIG_HEAD). And of course have\n\"git merge --abort\" (or even \"git pull --abort\") as a porcelain.\n\n-- \nJakub Narebski\nPoland\n"},{"id":"105896","messageId":"43d8ce650902230441n51c9e5a8h722682cda778aa7a@mail.gmail.com","threadId":"17897","inReplyTo":"200902211118.32185.jnareb@gmail.com","subject":"Re: git merge --abort","fromName":"John Tapsell","fromEmail":"johnflux@gmail.com","sentAt":"2009-02-23T12:41:03Z","receivedAt":"2009-02-23T12:41:03Z","isPatch":false,"sender":{"key":"johnflux@gmail.com","avatar":"https://gravatar.com/avatar/25f70d4c0f96396b84a2e34bcd9bdc233462c7b4be29b5fdca8266fc53f30b0c?d=mp&s=160"},"body":"2009/2/21 Jakub Narebski <jnareb@gmail.com>:\n> On Sat, 21 Feb 2009, Junio C Hamano wrote:\n>> Jakub Narebski <jnareb@gmail.com> writes:\n>>\n>> > Perhaps this is the case fo \"feature that waits for a user\", namely\n>> > 'git stash --no-reset', which would save a state just in case, perhaps\n>> > in a separate area and not refs/stash (ORIG_STASH perhaps?).\n>>\n>> Isn't that Nana's \"git stash --keep\" patch posted a few weeks ago sitting\n>> in \"pu\"?\n>\n> Almost exactly.\n>\n> When using it as a safety measure (perhaps enabled via configuration\n> variable, similarly to core.safecrlf or diff.autoRefreshIndex) we would\n> probably want to not save it in 'refs/stash' stack, but in single-use\n> ORIG_STATE (similar to HEAD reflog vs. ORIG_HEAD). And of course have\n> \"git merge --abort\" (or even \"git pull --abort\") as a porcelain.\n\nIt sounds like we have some sort of plan then.  Will Nana's patch be\ncommitted into mainline git?  Then we can add the --abort porcelain\n"},{"id":"105957","messageId":"7vvdr0obuj.fsf@gitster.siamese.dyndns.org","threadId":"17897","inReplyTo":"43d8ce650902230441n51c9e5a8h722682cda778aa7a@mail.gmail.com","subject":"Re: git merge --abort","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-02-24T01:36:04Z","receivedAt":"2009-02-24T01:36:04Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"John Tapsell <johnflux@gmail.com> writes:\n\n> It sounds like we have some sort of plan then.  Will Nana's patch be\n> committed into mainline git?  Then we can add the --abort porcelain\n\nI do not know what plan you are talking about, but that's not how the\ndevelopment works.  If something is merged to 'pu', and you have a cool\nfeature you would want to take advantage of it, you can build your cool\nfeature on top of that particular topic.  If the result looks reasonable\nthey would cook for a while in 'next' for further polishing and then\nfinally go to 'mainline'.\n\nI personally did not think \"--keep\" would need to be be part of a\nreasonable \"merge --abort\" implementation, but I may have missed some\ndescription of a viable design discussed on the list.\n"},{"id":"105958","messageId":"200902240253.35470.jnareb@gmail.com","threadId":"17897","inReplyTo":"7vvdr0obuj.fsf@gitster.siamese.dyndns.org","subject":"Re: git merge --abort","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2009-02-24T01:53:34Z","receivedAt":"2009-02-24T01:53:34Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Junio C Hamano wrote:\n> John Tapsell <johnflux@gmail.com> writes:\n> \n> > It sounds like we have some sort of plan then.  Will Nana's patch be\n> > committed into mainline git?  Then we can add the --abort porcelain\n> \n> I do not know what plan you are talking about, but that's not how the\n> development works.  If something is merged to 'pu', and you have a cool\n> feature you would want to take advantage of it, you can build your cool\n> feature on top of that particular topic.  If the result looks reasonable\n> they would cook for a while in 'next' for further polishing and then\n> finally go to 'mainline'.\n> \n> I personally did not think \"--keep\" would need to be be part of a\n> reasonable \"merge --abort\" implementation, but I may have missed some\n> description of a viable design discussed on the list.\n\nMy idea was that merge would do the following:\n\n  $ <save stash into MERGE_STASH or similar, no reset>\n  $ <do a merge>\n\nThen we have two possibilities:\n\n  # merge failed with conflicts\n  $ git merge --abort (would unstash MERGE_STASH and delete it)\n\n  # we created merge conflict\n  $ <MERGE_STASH is removed together with MERGE_HEAD>\n\n-- \nJakub Narebski\nPoland\n"},{"id":"105960","messageId":"7vk57goanf.fsf@gitster.siamese.dyndns.org","threadId":"17897","inReplyTo":"200902240253.35470.jnareb@gmail.com","subject":"Re: git merge --abort","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-02-24T02:01:56Z","receivedAt":"2009-02-24T02:01:56Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jakub Narebski <jnareb@gmail.com> writes:\n\n> Junio C Hamano wrote:\n>> John Tapsell <johnflux@gmail.com> writes:\n>> \n>> > It sounds like we have some sort of plan then.  Will Nana's patch be\n>> > committed into mainline git?  Then we can add the --abort porcelain\n>> \n>> I do not know what plan you are talking about, but that's not how the\n>> development works.  If something is merged to 'pu', and you have a cool\n>> feature you would want to take advantage of it, you can build your cool\n>> feature on top of that particular topic.  If the result looks reasonable\n>> they would cook for a while in 'next' for further polishing and then\n>> finally go to 'mainline'.\n>> \n>> I personally did not think \"--keep\" would need to be be part of a\n>> reasonable \"merge --abort\" implementation, but I may have missed some\n>> description of a viable design discussed on the list.\n>\n> My idea was that merge would do the following:\n>\n>   $ <save stash into MERGE_STASH or similar, no reset>\n>   $ <do a merge>\n>\n> Then we have two possibilities:\n>\n>   # merge failed with conflicts\n>   $ git merge --abort (would unstash MERGE_STASH and delete it)\n\nHere \"would unstash\" needs to follow something else, namely, make your\nwork tree free of local changes.  How?  \"reset --hard\"?\n\n>   # we created merge conflict\n>   $ <MERGE_STASH is removed together with MERGE_HEAD>\n\nYou mean \"created a merge without conflict\", right?  That part is easy to\nguess and understand.\n\nIn fact, when you run more than one strategies, something similar to this\nalready happens internally.  The C version may be harder to follow, but\nyou can check the last scripted version contrib/examples/git-merge.sh and\nfind two functions, savestate/restorestate pair, that does exactly that.\n\nIt way predates --keep patch, by the way.\n"},{"id":"106039","messageId":"200902241051.42800.jnareb@gmail.com","threadId":"17897","inReplyTo":"7vk57goanf.fsf@gitster.siamese.dyndns.org","subject":"Re: git merge --abort","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2009-02-24T09:51:41Z","receivedAt":"2009-02-24T09:51:41Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Junio C Hamano wrote::\n> Jakub Narebski <jnareb@gmail.com> writes:\n>> Junio C Hamano wrote:\n\n>>> I personally did not think \"--keep\" would need to be be part of a\n>>> reasonable \"merge --abort\" implementation, but I may have missed some\n>>> description of a viable design discussed on the list.\n\nFirst, a description of state: here we assume that you have changes to\ntracked files in working area that are neither in HEAD, nor in index,\nand that you can have changes in index which are neither in HEAD nor\nin working area.\n\nIf HEAD == index == working area then stashing is not necessary.\n\n>> My idea was that merge would do the following:\n>>\n>>   $ <save stash into MERGE_STASH or similar, no reset>\n>>   $ <do a merge>\n>>\n>> Then we have two possibilities:\n>>\n>>   # merge failed with conflicts\n>>   $ git merge --abort (would unstash MERGE_STASH and delete it)\n> \n> Here \"would unstash\" needs to follow something else, namely, make your\n> work tree free of local changes.  How?  \"reset --hard\"?\n\nYes. \"git merge --abort\" would be equivalent to\n\n  $ git reset --hard ORIG_HEAD\n  $ git stash pop --ref=MERGE_STASH\n  $ rm $GIT_DIR/MERGE_STASH\n\n> \n>>   # we created merge conflict\n>>   $ <MERGE_STASH is removed together with MERGE_HEAD>\n> \n> You mean \"created a merge without conflict\", right?  That part is easy to\n> guess and understand.\n\nYes. I meant here: \"created merge _commit_\" (not \"conflict\").\n\n> \n> In fact, when you run more than one strategies, something similar to this\n> already happens internally.  The C version may be harder to follow, but\n> you can check the last scripted version contrib/examples/git-merge.sh and\n> find two functions, savestate/restorestate pair, that does exactly that.\n> \n> It way predates --keep patch, by the way.\n\nWell, we have \"git reset --merge ORIG_HEAD\" which from what I understand\ndoes at least part of \"git merge --abort\", but I am not sure if it\ncovers all cases (like dirty index in addition to dirty tree).\n\n-- \nJakub Narebski\nPoland\n"}]}