Re: [PATCH v2] Teach merge the '[-e|--edit]' option

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



[Adding Ram to the Cc: list as this topic has much to do with resuming a
sequencer-driven workflow, and dropping Todd who does not seem to have
much to say on this topic]

Jay Soffian <jaysoffian@xxxxxxxxx> writes:

> I am complaining that git-merge implements commits internally, which
> gives it unique behavior from git-{commit/cherry-pick/revert} (the
> latter two of which just run external git-commit). I'm saying merge is
> fundamentally broken to do it this way. And maybe that's something
> that should be fixed in 2.0 -- that git-merge should just call out to
> git-commit, just like cherry-pick/revert do.

The purpose of the plumbing commands, e.g. commit-tree, is to implement a
unit of logical step at the mechanical level well without enforcing policy
decisions that may not apply to all situations.

On the other hand, the purpose of the Porcelain commands is to support a
concrete workflow element. "git commit" should support what users want to
happen when advancing the history by one commit, "git pull" should support
what users want to happen when integrating work done in another repository
to the history you are currently growing, etc. It is where we should and
do allow users to implement their own policy with hooks and configuration
variables when they want to, and it is even fine if we implemented sane
default policies with ways to override them (e.g. "commit --allow-empty",
"merge --no-ff").

Some Porcelain commands cannot complete their workflow element by
themselves in certain situations without getting help from users, and they
give control back to the user when they need such help. "git rebase", "git
am", "git merge", etc. can and do stop and ask the user to help resolving
conflicts.

The unfortunate historical accident that we may want to correct is that
some of these "we stopped in the middle and asked the user to help before
continuing" situation were presented as if "we stopped and aborted in the
middle, leaving the user to fix up the mess", which is a completely wrong
mental model. "Upon conflicts, 'git merge' stops in the middle, and you
complete it with 'git commit'" is a prime example of this. We even wrongly
label such a situation as "failed merge". It is not failed---it merely is
not auto-completed and waiting to be completed with user's help.

To understand why it is a wrong mental model, you need to imagine a world
where the logic to resolve conflicts in "git merge" is improved so that it
needs less help from the users. rerere.autoupdate is half-way there---the
user allows the merge machinery to take advantage of conflict resolutions
that the user has performed previously. Even though we currently do not
let "git merge" proceed to commit the result, it is entirely plausible to
go one step further and treat the resulting tree from applying the rerere
information as the result of the automerge. When that happens, it is very
natural for the user to expect that the rest of what "git merge" does for
a clean automerge to be carried out. After all, from the end user's point
of view, it _is_ a clean auto-merge. The only difference is how the user
helped the automerge machinery.

The root cause of the inconsistencies you are bringing up (which I agree
are annoying and I further agree that it is a worthy thing to address) is
that even though we tell the users "after helping the 'git merge', you
conclude it with 'git commit'", the concluding 'git commit' does _not_
perform what the user configured 'git merge' to do before a merge is
concluded, unlike a cleanly resolved 'git merge'.

This is merely an unfortunate historical accident. Because "git merge" did
not have any user configurable policy decisions (read: hooks) when this
"conclude with commit" was coded, "conclude with commit" was sufficient to
emulate the case where the merge did not need any help from the user.

But it no longer is true with modern Git.

With more recent changes, e.g. the sequencer work and "git cherry-pick"
that takes multiple commits, "conclude with commit" is becoming less and
less correct thing to say. The workflow elements these commands implement
do have "create a commit" as one essential part, but that is not the only
thing they do. If anything, I think the right way forward is to update the
UI with this rule for consistency:

  Some tools can stop in the middle when they cannot automatically compute
  the outcome, and give control back to the user asking for help. After
  helping these tool, the way to resume what was being done is to invoke
  the tool with the "--continue" option. All user level policy decisions
  implemented by hooks and configurations the tool normally obey when it
  does not need such help from the end user are obeyed when continuing.

I wouldn't mind if that is "invoke 'git continue' command", even though I
suspect that may make the implementation slightly more complex (I haven't
thought things through). "git commit" as a way to conclude a merge that
was stopped in the middle due to a conflict should be deprecated in the
longer term, like say in Git 2.0 someday.


[Footnote]

*1* By the way, "git merge --no-commit" is an oddball. It primarily is
used when the user does _not_ want the resulting commit but wants to
further modify the tree state (e.g. cherry picking a part of what was done
in the side branch). At the philosophical level, the user should be using
merge machinery at the "plumbing" level (e.g. merge-recursive backend),
but the interface to invoke the plumbing level merge machinery is so
arcane (they are after all designed for scripts not for humans) that
nobody does so in practice. And for that purpose, I think it is Ok for the
user to do anything after "git merge --no-commit" finishes (either leaving
conflicts or leaving a cleanly merged state), including "git commit".
Because that "git commit" is very different from the "conclude conflicted
merge with commit" which is a poor substitute for "git merge --continue"
in modern Git, I think it is perfectly fine and even preferable if it does
not obey any "git merge" semantics (i.e. user defined policy that pertains
to "merge" operations).


--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]