Subject: bug#20292: 24.5; Saving Git-controlled file with merge conflicts after "stash pop" stages the file

From: Dmitry Gutov <[email-masked]>
Date: Thu, 17 Nov 2016 00:45:43 +0200

On 16.11.2016 19:30, Eli Zaretskii wrote:

> I don't even see the message you are responding to.  Was it sent only
> to you, Dmitry?

It was addressed to both me and the bug email, but didn't arrive at the 
latter. I'm attaching the full message here.

>> You, as a core Git developer, represent the informed minority, and as
>> such, it's probably not too much to expect that you and the others can
>> customize vc-git-resolve-conflicts to nil without much trouble.
>
> Perhaps there could be a way to customize vc-git so that it caters to
> such advanced users?

vc-git-resolve-conflicts is already a user option.

Were you thinking of something else?

Subject: Re: bug#20292: 24.5; Saving Git-controlled file with merge conflicts after "stash pop" stages the file
From: Junio C Hamano <[email-masked]>
To: [email-masked]
Cc: Dmitry Gutov <[email-masked]>
Date: Thu, 27 Oct 2016 10:20:52 -0700

Sorry for responding to an ancient message, but you said

> When a stash contains changes for several files, and "stash pop"
> encounters conflicts only in some of them, the rest of the files are
> stages automatically.
> 
> So then when we unstage the files which had conflicts after
> resolving those, the result is mixed. Which doesn't look right.

But this is a completely normal and designed way how conflicts are
resolved during any "mergy" operations in Git.  It is not limited to
"stash pop" (or "stash apply").  "git merge", "git cherry-pick",
"git revert", "git am -3" and even "git checkout -m another-branch"
share this feature.

When doing a mergy operation, some paths will merge cleanly and some
paths will have conflicts.  A conflicted path will

 - leave multiple stages in the index; the common ancestor version
   in stage#1, the version you originally had in stage#2, and the
   version the mergy operation wanted to bring the changes from into
   your state in stage#3.

 - have conflicted merge result in the working tree, with the
   conflict markers.

The way Git is designed to be used is for the user to edit the
latter to come up with a conflict resolution in the working tree,
then add that result to the index, after the user is satisfied with
it, before continuing (typically, but not necessarily, to record the
result with "git commit").

Now, what about the cleanly automerged paths?  They are added to the
index and this is by design.  You can see why this is necessary by
doing:

 - Start a mergy operation (e.g.  "stash pop", or "git merge") that
   conflicts;

 - Resolve the conflicts in the working tree,

 - But before doing "git add" to tell Git that you are done with
   these paths, run "git diff" (no other parameters).  You may have
   to (setq vc-git-resolve-conflicts nil) for that

You will notice that this invocation of "git diff" show concisely
how the result of your conflict resolution differs from either of
the branch.  This is used by Git users as one of the final step of
verification before telling Git "I now am done with the conflict in
this path and resolution is good" by issuing "git add" for the path.

You will also notice that this invocation of "git diff" does not
clutter with changes that have been auto-merged cleanly.  At this
step of the workflow to resolve conflicts, the user is concentrating
on the paths that had conflicts, and it is crucial that cleanly
auto-merged paths do not get in the way.  The user can still view
the overall picture by asking "git diff HEAD" (to see both
automerged result and hand-resolved result, the latter of which may
or may not have been added to the index) and "git diff --cached" (to
see automerged result and hand-resolved and then "git add"'ed
result).

So, there is no "Bad news, everybody!" in the behaviour you
observed.

> What shall we do? Unstage the automatically-staged files? Revert the
> changes from this bug? It seems Git really wants the changes staged
> after the conflict resolution.

I do not know what you thought you can achieve by "unstage the
auto-merged paths?" here, but perhaps you were expecting "git diff"
(no arguments) would be the way to view all the changes that a mergy
operation with conflicted states brought in?  If that (i.e. "view
all the changes") was what you wanted to achieve, then neither
"unstage the auto-merged paths" nor "automatically 'git add' upon
saving the buffer" is a good solution.  

I was told by somebody that the message I am responding to
eventually resulted in vc-git-resolve-conflicts that defaults to
true in Emacs 25.1, which lead to "automatically 'git add' upon
saving the buffer".  I think this variable and its default is a big
disservice to Git users' whose daily work involves lots of conflict
resolutions in mergy operations.

Running "git diff HEAD" instead of "git diff" may be the solution,
if the problem were "I want to view all the changes, both already
added to the index and the ones that have not been yet", though I
am not sure from the "Bad news, everybody!" message if that is the
problem you were trying to solve.