git merge --abort

classic Classic list List threaded Threaded
18 messages Options
Reply | Threaded
Open this post in threaded view
|

git merge --abort

John Tapsell
Hi,

 I hope you don't mind me generating lots of noise here..

  It's not obvious how to abort a merge between two trees.  Would
aliasing  "git merge --abort"  to "git reset --hard"  be sensible?  Is
there a better way to abort a merge?  Especially if you have
uncommitted changes.

  If that idea isn't liked, instead maybe we can add a note to 'git
merge --help' on how to abort.

John
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: git merge --abort

Junio C Hamano
John Tapsell <[hidden email]> writes:

>   It's not obvious how to abort a merge between two trees.  Would
> aliasing  "git merge --abort"  to "git reset --hard"  be sensible?

Not at all.  Especially when you have local changes.

There are two classes of users who would get themselves into a conflicted
merge while they have local changes.  One is people who know what they are
doing (like Linus) run "git pull" while having small set of disposable
local changes they do not mind losing, and they know how to recover.  The
other is recent CVS/SVN migrants who learned (incorrectly) that "git pull"
is similar to "cvs update" from wrong sources that say "it is a way to get
changes made by other people while you have a half-baked mess that is
still not ready to be committed in your work tree" (which is not) [*1*].

"git reset --hard" is the last thing you would want to suggest to the
latter class of people.

Immediately after a merge result in conflicts, there should be two kinds
of paths that are different from HEAD:

 * The ones you had local modifications before you started the failed
   merge.  They should be left intact after "merge --abort".

 * The ones you did not have local modifications, but merge could not
   automatically resolve.  There may be files with conflicted marker in
   the work tree, or there may be not.

If you had local modifications to a path that would be involved in the
merge, the merge *ought to* stop before even touching the index nor the
work tree [*2*].  Merge would not start if you had any staged changes in
the index.  So the recovery strategy for "merge --abort" needs to only
worry about the above two cases.  The correct implementation would be
roughly:

 - If the index does not have any unmerged entries, stop.  The merge did
   not do anything, and there is nothing to abort.

 - For each path that has unmerged entries in the index:

   - If the path does not exist in HEAD, drop the unmerged index entries
     for the path, without touching the work tree (if a file exists there,
     it must have existed as an untracked file before the merge started);

   - If the path does exist in HEAD, discard the unmerged index entries,
     reset the path in the index from HEAD, and write that out to the work
     tree.

 - For each path whose entry is stage #0 in the index, if it is different
   from HEAD:

   - If it does not exist in HEAD, drop it from the index and remove the
     file from the work tree.  It is a file added by the failed merge and
     couldn't have existed as an untracked file before the merge started.

   - If it does exist in HEAD, reset the path in the index from HEAD, and
     write that out to the work tree.

But the above would be correct *only* immediately after a failed merge.
The user could be giving up after having done any random things after a
failed merge in an attempt to resolve, and at that point we cannot trust
the state of the index nor the work tree.  The simplest example to
illustrate:

    $ edit goodbye.c ;# without "git add"
    $ git merge other
    Conflict in hello.c
    $ git add goodbye.c
    $ git merge --abort ;# ???

The user's "git add goodbye.c" will make the state of the index unusable
for the above outlined algorithm to tell what was changed by the merge and
what were already different before the merge.

So in general, even "merge --abort" implemented according to the above
outline cannot be sold as "a safe procedure to recover to where you were
before you started the last failed merge".  There is no such thing, unless
you really educate the user not to expect miracle.

If you mistakenly run "git merge" while your index is already unmerged
(iow, after a failed merge before you resolved it nor resetted the index),
the command aborts without touching the index nor the work tree.  If you
implement "merge --abort" as outlined above, it will try to abort the
previous conflicted merge, not this round which did not do anything, but
again, the user could have done any other random things in addition to the
attempt to run the second "git merge".

Having said all that, I suspect

        $ git reset --merge HEAD

may do the right thing, if your git already has the option ;-)


[Footnote]

*1* CVS/SVN want to linearize so even if your local changes want to go
directy on top of what you checked out, "cvs update" tries to replay your
uncommitted changes on top of what comes as the latest from the central
server, which could result in conflicts.  With git, you do not have to
risk losing your local changes that way.  Instead, you can commit your
local changes and then "git pull" will try to merge.  The merge can
conflict and leave the same mess as "cvs update" would leave when it tries
to replay your uncommitted changes, but a _huge_ difference here is that
you get only one chance to resolve that conflict with CVS/SVN (because
nothing records your local changes before the "update") and if you screw
that up, you are out of luck.  With git, you have the local commit that
records the changes you did on top of the old tip of the branch, and you
can redo the merge.

*2* I say *ought to*, and I am reasonably sure resolve strategy works
correctly, but I wouldn't be surprised if recursive strategy which is the
default these days still have corner case bugs when the merge involves
renames and/or D/F conflicts).
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: git merge --abort

John Tapsell
2009/2/19 Junio C Hamano <[hidden email]>:
> John Tapsell <[hidden email]> writes:
>
>>   It's not obvious how to abort a merge between two trees.  Would
>> aliasing  "git merge --abort"  to "git reset --hard"  be sensible?
>
> Not at all.  Especially when you have local changes.

Just to confirm that I've understood this - there's currently no way
at the moment to 'cancel' an abort.  In the example you gave:

>    $ edit goodbye.c ;# without "git add"
>    $ git merge other
>    Conflict in hello.c
>    $ git add goodbye.c
>    $ git merge --abort ;# ???

There's no reliable way of getting back to the state before the merge?


> The user's "git add goodbye.c" will make the state of the index unusable
> for the above outlined algorithm to tell what was changed by the merge and
> what were already different before the merge.
>
> So in general, even "merge --abort" implemented according to the above
> outline cannot be sold as "a safe procedure to recover to where you were
> before you started the last failed merge".  There is no such thing, unless
> you really educate the user not to expect miracle.
>
> If you mistakenly run "git merge" while your index is already unmerged
> (iow, after a failed merge before you resolved it nor resetted the index),
> the command aborts without touching the index nor the work tree.  If you
> implement "merge --abort" as outlined above, it will try to abort the
> previous conflicted merge, not this round which did not do anything, but
> again, the user could have done any other random things in addition to the
> attempt to run the second "git merge".
>
> Having said all that, I suspect
>
>        $ git reset --merge HEAD
>
> may do the right thing, if your git already has the option ;-)
>
>
> [Footnote]
>
> *1* CVS/SVN want to linearize so even if your local changes want to go
> directy on top of what you checked out, "cvs update" tries to replay your
> uncommitted changes on top of what comes as the latest from the central
> server, which could result in conflicts.  With git, you do not have to
> risk losing your local changes that way.  Instead, you can commit your
> local changes and then "git pull" will try to merge.  The merge can
> conflict and leave the same mess as "cvs update" would leave when it tries
> to replay your uncommitted changes, but a _huge_ difference here is that
> you get only one chance to resolve that conflict with CVS/SVN (because
> nothing records your local changes before the "update") and if you screw
> that up, you are out of luck.  With git, you have the local commit that
> records the changes you did on top of the old tip of the branch, and you
> can redo the merge.
>
> *2* I say *ought to*, and I am reasonably sure resolve strategy works
> correctly, but I wouldn't be surprised if recursive strategy which is the
> default these days still have corner case bugs when the merge involves
> renames and/or D/F conflicts).
>
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: git merge --abort

Jay Soffian
On Thu, Feb 19, 2009 at 8:34 AM, John Tapsell <[hidden email]> wrote:
> There's no reliable way of getting back to the state before the merge?

Sure there is. Commit or stash before you merge, so that your index
and working copy are clean.

j.
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: git merge --abort

John Tapsell
2009/2/19 Jay Soffian <[hidden email]>:
> On Thu, Feb 19, 2009 at 8:34 AM, John Tapsell <[hidden email]> wrote:
>> There's no reliable way of getting back to the state before the merge?
>
> Sure there is. Commit or stash before you merge, so that your index
> and working copy are clean.

Could a stash be done automatically by the merge command, for just a case?

John
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: git merge --abort

Junio C Hamano
John Tapsell <[hidden email]> writes:

> 2009/2/19 Jay Soffian <[hidden email]>:
>> On Thu, Feb 19, 2009 at 8:34 AM, John Tapsell <[hidden email]> wrote:
>>> There's no reliable way of getting back to the state before the merge?
>>
>> Sure there is. Commit or stash before you merge, so that your index
>> and working copy are clean.
>
> Could a stash be done automatically by the merge command, for just a case?

It cuts both ways.  For people who work on a well organized project
(i.e. highly modularized) and tend to keep local changes in the work tree
while doing a lot of merges, running "stash" every time would (1) remove
the local change from the work tree, which he has to remember to manually
unstash after resolving conflicts in the merge (which would not have
conflicted with the local change anyway), which is an additional work for
no real gain, and (2) clutter his stash.  My gut feeling is that it is a
change that affects the way the end user has to work that is sufficiently
different and disruptive for no real gain.

If you read the original message more carefully, you will notice that the
suggested "git merge --abort" would break down *only* if the user messes
with the state conflicted merge left.  And an unmanageable conflicts are
much rare compared to most merges that autoresolve, so you should optimze
for the common case while giving a way to gain safety only when needed.

Probably a much better workflow, if we add "merge --abort", would be:

    $ edit ;# unrelated local changes are still here
    $ git pull ;# or merge or whatever
    ... oops, large conflict ...
    ... look and see if it can easily be resolved ...
    ... otherwise
    $ git merge --abort
    $ git stash
    $ git pull ;# or whatever, try again
    ... the same conflict but this time you only need to worry
    ... about the merge itself
    ... resolve, review, test to convince yourself that your
    ... resolution is good and then...
    $ git commit
    $ git stash pop
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: git merge --abort

John Tapsell
2009/2/20 Junio C Hamano <[hidden email]>:
<snip>
>    $ edit ;# unrelated local changes are still here
>    $ git pull ;# or merge or whatever
>    ... oops, large conflict ...
>    ... look and see if it can easily be resolved ...
>    ... otherwise
>    $ git merge --abort

Can I just confirm - at this stage, "git merge --abort" would be a
"git reset --hard HEAD" ?

So could "git pull/merge" detect if there were local changes, and if
there are tell the user something along the lines that they have to
either abort the merge, or be unable to abort later?

>    $ git stash
>    $ git pull ;# or whatever, try again
>    ... the same conflict but this time you only need to worry
>    ... about the merge itself
>    ... resolve, review, test to convince yourself that your
>    ... resolution is good and then...
>    $ git commit
>    $ git stash pop
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: git merge --abort

Junio C Hamano
John Tapsell <[hidden email]> writes:

> 2009/2/20 Junio C Hamano <[hidden email]>:
> <snip>
>>    $ edit ;# unrelated local changes are still here
>>    $ git pull ;# or merge or whatever
>>    ... oops, large conflict ...
>>    ... look and see if it can easily be resolved ...
>>    ... otherwise
>>    $ git merge --abort
>
> Can I just confirm - at this stage, "git merge --abort" would be a
> "git reset --hard HEAD" ?

Not at all.  Please re-read my previous message that begins with "Not at
all".
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: git merge --abort

John Tapsell
2009/2/20 Junio C Hamano <[hidden email]>:

> John Tapsell <[hidden email]> writes:
>
>> 2009/2/20 Junio C Hamano <[hidden email]>:
>> <snip>
>>>    $ edit ;# unrelated local changes are still here
>>>    $ git pull ;# or merge or whatever
>>>    ... oops, large conflict ...
>>>    ... look and see if it can easily be resolved ...
>>>    ... otherwise
>>>    $ git merge --abort
>>
>> Can I just confirm - at this stage, "git merge --abort" would be a
>> "git reset --hard HEAD" ?
>
> Not at all.  Please re-read my previous message that begins with "Not at all".

Doh sorry.  Yeah it has to be that long algorithm that you outlined.
Can it be done with a series of currently existing commands?  Can I
persuade someone else to implement it ? :-)

John
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: git merge --abort

Bryan Donlan
In reply to this post by Junio C Hamano
On Fri, Feb 20, 2009 at 12:24 AM, Junio C Hamano <[hidden email]> wrote:

> John Tapsell <[hidden email]> writes:
>
>> 2009/2/19 Jay Soffian <[hidden email]>:
>>> On Thu, Feb 19, 2009 at 8:34 AM, John Tapsell <[hidden email]> wrote:
>>>> There's no reliable way of getting back to the state before the merge?
>>>
>>> Sure there is. Commit or stash before you merge, so that your index
>>> and working copy are clean.
>>
>> Could a stash be done automatically by the merge command, for just a case?
>
> It cuts both ways.  For people who work on a well organized project
> (i.e. highly modularized) and tend to keep local changes in the work tree
> while doing a lot of merges, running "stash" every time would (1) remove
> the local change from the work tree, which he has to remember to manually
> unstash after resolving conflicts in the merge (which would not have
> conflicted with the local change anyway), which is an additional work for
> no real gain, and (2) clutter his stash.  My gut feeling is that it is a
> change that affects the way the end user has to work that is sufficiently
> different and disruptive for no real gain.

Perhaps a better approach would be to stash the pre-merge state in the
reflog, then? That is, manufacture a pre-merge commit containing all
files changed in the working copy, and add it to the reflog prior to
performing a merge. git merge --abort can then simply check whether
the top reflog entry is a pre-merge state, and if so, reset --hard to
it, then reset the index to the parent of our pre-merge commit.

This would also nicely handle the case where the user tries some
random things before deciding to abort the merge.
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: git merge --abort

Jakub Narębski
Bryan Donlan <[hidden email]> writes:

> On Fri, Feb 20, 2009 at 12:24 AM, Junio C Hamano <[hidden email]> wrote:
>> John Tapsell <[hidden email]> writes:
>>> 2009/2/19 Jay Soffian <[hidden email]>:
>>>> On Thu, Feb 19, 2009 at 8:34 AM, John Tapsell <[hidden email]> wrote:
>>>>>
>>>>> There's no reliable way of getting back to the state before the merge?
>>>>
>>>> Sure there is. Commit or stash before you merge, so that your index
>>>> and working copy are clean.
>>>
>>> Could a stash be done automatically by the merge command, for just a case?
>>
>> It cuts both ways.  For people who work on a well organized project
>> (i.e. highly modularized) and tend to keep local changes in the work tree
>> while doing a lot of merges, running "stash" every time would (1) remove
>> the local change from the work tree, which he has to remember to manually
>> unstash after resolving conflicts in the merge (which would not have
>> conflicted with the local change anyway), which is an additional work for
>> no real gain, and (2) clutter his stash.  My gut feeling is that it is a
>> change that affects the way the end user has to work that is sufficiently
>> different and disruptive for no real gain.
>
> Perhaps a better approach would be to stash the pre-merge state in the
> reflog, then? That is, manufacture a pre-merge commit containing all
> files changed in the working copy, and add it to the reflog prior to
> performing a merge. git merge --abort can then simply check whether
> the top reflog entry is a pre-merge state, and if so, reset --hard to
> it, then reset the index to the parent of our pre-merge commit.
>
> This would also nicely handle the case where the user tries some
> random things before deciding to abort the merge.

Perhaps this is the case fo "feature that waits for a user", namely
'git stash --no-reset', which would save a state just in case, perhaps
in a separate area and not refs/stash (ORIG_STASH perhaps?).

What do you think about this idea?
--
Jakub Narebski
Poland
ShadeHawk on #git
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: git merge --abort

Junio C Hamano
Jakub Narebski <[hidden email]> writes:

> Perhaps this is the case fo "feature that waits for a user", namely
> 'git stash --no-reset', which would save a state just in case, perhaps
> in a separate area and not refs/stash (ORIG_STASH perhaps?).

Isn't that Nana's "git stash --keep" patch posted a few weeks ago sitting
in "pu"?
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: git merge --abort

Jakub Narębski
On Sat, 21 Feb 2009, Junio C Hamano wrote:
> Jakub Narebski <[hidden email]> writes:
>
> > Perhaps this is the case fo "feature that waits for a user", namely
> > 'git stash --no-reset', which would save a state just in case, perhaps
> > in a separate area and not refs/stash (ORIG_STASH perhaps?).
>
> Isn't that Nana's "git stash --keep" patch posted a few weeks ago sitting
> in "pu"?

Almost exactly.

When using it as a safety measure (perhaps enabled via configuration
variable, similarly to core.safecrlf or diff.autoRefreshIndex) we would
probably want to not save it in 'refs/stash' stack, but in single-use
ORIG_STATE (similar to HEAD reflog vs. ORIG_HEAD). And of course have
"git merge --abort" (or even "git pull --abort") as a porcelain.

--
Jakub Narebski
Poland
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: git merge --abort

John Tapsell
2009/2/21 Jakub Narebski <[hidden email]>:

> On Sat, 21 Feb 2009, Junio C Hamano wrote:
>> Jakub Narebski <[hidden email]> writes:
>>
>> > Perhaps this is the case fo "feature that waits for a user", namely
>> > 'git stash --no-reset', which would save a state just in case, perhaps
>> > in a separate area and not refs/stash (ORIG_STASH perhaps?).
>>
>> Isn't that Nana's "git stash --keep" patch posted a few weeks ago sitting
>> in "pu"?
>
> Almost exactly.
>
> When using it as a safety measure (perhaps enabled via configuration
> variable, similarly to core.safecrlf or diff.autoRefreshIndex) we would
> probably want to not save it in 'refs/stash' stack, but in single-use
> ORIG_STATE (similar to HEAD reflog vs. ORIG_HEAD). And of course have
> "git merge --abort" (or even "git pull --abort") as a porcelain.

It sounds like we have some sort of plan then.  Will Nana's patch be
committed into mainline git?  Then we can add the --abort porcelain
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: git merge --abort

Junio C Hamano
John Tapsell <[hidden email]> writes:

> It sounds like we have some sort of plan then.  Will Nana's patch be
> committed into mainline git?  Then we can add the --abort porcelain

I do not know what plan you are talking about, but that's not how the
development works.  If something is merged to 'pu', and you have a cool
feature you would want to take advantage of it, you can build your cool
feature on top of that particular topic.  If the result looks reasonable
they would cook for a while in 'next' for further polishing and then
finally go to 'mainline'.

I personally did not think "--keep" would need to be be part of a
reasonable "merge --abort" implementation, but I may have missed some
description of a viable design discussed on the list.
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: git merge --abort

Jakub Narębski
Junio C Hamano wrote:

> John Tapsell <[hidden email]> writes:
>
> > It sounds like we have some sort of plan then.  Will Nana's patch be
> > committed into mainline git?  Then we can add the --abort porcelain
>
> I do not know what plan you are talking about, but that's not how the
> development works.  If something is merged to 'pu', and you have a cool
> feature you would want to take advantage of it, you can build your cool
> feature on top of that particular topic.  If the result looks reasonable
> they would cook for a while in 'next' for further polishing and then
> finally go to 'mainline'.
>
> I personally did not think "--keep" would need to be be part of a
> reasonable "merge --abort" implementation, but I may have missed some
> description of a viable design discussed on the list.

My idea was that merge would do the following:

  $ <save stash into MERGE_STASH or similar, no reset>
  $ <do a merge>

Then we have two possibilities:

  # merge failed with conflicts
  $ git merge --abort (would unstash MERGE_STASH and delete it)

  # we created merge conflict
  $ <MERGE_STASH is removed together with MERGE_HEAD>

--
Jakub Narebski
Poland
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: git merge --abort

Junio C Hamano
Jakub Narebski <[hidden email]> writes:

> Junio C Hamano wrote:
>> John Tapsell <[hidden email]> writes:
>>
>> > It sounds like we have some sort of plan then.  Will Nana's patch be
>> > committed into mainline git?  Then we can add the --abort porcelain
>>
>> I do not know what plan you are talking about, but that's not how the
>> development works.  If something is merged to 'pu', and you have a cool
>> feature you would want to take advantage of it, you can build your cool
>> feature on top of that particular topic.  If the result looks reasonable
>> they would cook for a while in 'next' for further polishing and then
>> finally go to 'mainline'.
>>
>> I personally did not think "--keep" would need to be be part of a
>> reasonable "merge --abort" implementation, but I may have missed some
>> description of a viable design discussed on the list.
>
> My idea was that merge would do the following:
>
>   $ <save stash into MERGE_STASH or similar, no reset>
>   $ <do a merge>
>
> Then we have two possibilities:
>
>   # merge failed with conflicts
>   $ git merge --abort (would unstash MERGE_STASH and delete it)

Here "would unstash" needs to follow something else, namely, make your
work tree free of local changes.  How?  "reset --hard"?

>   # we created merge conflict
>   $ <MERGE_STASH is removed together with MERGE_HEAD>

You mean "created a merge without conflict", right?  That part is easy to
guess and understand.

In fact, when you run more than one strategies, something similar to this
already happens internally.  The C version may be harder to follow, but
you can check the last scripted version contrib/examples/git-merge.sh and
find two functions, savestate/restorestate pair, that does exactly that.

It way predates --keep patch, by the way.
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: git merge --abort

Jakub Narębski
Junio C Hamano wrote::
> Jakub Narebski <[hidden email]> writes:
>> Junio C Hamano wrote:

>>> I personally did not think "--keep" would need to be be part of a
>>> reasonable "merge --abort" implementation, but I may have missed some
>>> description of a viable design discussed on the list.

First, a description of state: here we assume that you have changes to
tracked files in working area that are neither in HEAD, nor in index,
and that you can have changes in index which are neither in HEAD nor
in working area.

If HEAD == index == working area then stashing is not necessary.

>> My idea was that merge would do the following:
>>
>>   $ <save stash into MERGE_STASH or similar, no reset>
>>   $ <do a merge>
>>
>> Then we have two possibilities:
>>
>>   # merge failed with conflicts
>>   $ git merge --abort (would unstash MERGE_STASH and delete it)
>
> Here "would unstash" needs to follow something else, namely, make your
> work tree free of local changes.  How?  "reset --hard"?

Yes. "git merge --abort" would be equivalent to

  $ git reset --hard ORIG_HEAD
  $ git stash pop --ref=MERGE_STASH
  $ rm $GIT_DIR/MERGE_STASH

>
>>   # we created merge conflict
>>   $ <MERGE_STASH is removed together with MERGE_HEAD>
>
> You mean "created a merge without conflict", right?  That part is easy to
> guess and understand.

Yes. I meant here: "created merge _commit_" (not "conflict").

>
> In fact, when you run more than one strategies, something similar to this
> already happens internally.  The C version may be harder to follow, but
> you can check the last scripted version contrib/examples/git-merge.sh and
> find two functions, savestate/restorestate pair, that does exactly that.
>
> It way predates --keep patch, by the way.

Well, we have "git reset --merge ORIG_HEAD" which from what I understand
does at least part of "git merge --abort", but I am not sure if it
covers all cases (like dirty index in addition to dirty tree).

--
Jakub Narebski
Poland
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html