git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Elijah Newren <newren@gmail.com>
To: Josh Bleecher Snyder <josharian@gmail.com>
Cc: Git Mailing List <git@vger.kernel.org>
Subject: Re: git merge-tree: bug report and some feature requests
Date: Mon, 22 Jan 2018 09:58:04 -0800	[thread overview]
Message-ID: <CABPp-BGYs9jo16OZR8NsL-eO9LwEttBxBspvp1-_JjuD2oBYbA@mail.gmail.com> (raw)
In-Reply-To: <CAFAcib-2fxiVxtVWcbvafY3-Br7Y70HMiHFZoT0VfK6JU0Dp9A@mail.gmail.com>

On Sat, Jan 20, 2018 at 7:00 PM, Josh Bleecher Snyder
<josharian@gmail.com> wrote:
> Hi, all.
>
> I'm experimenting with some new porcelain for interactive rebase. One
> goal is to leave the work tree untouched for most operations. It looks
> to me like 'git merge-tree' may be the right plumbing command for
> doing the merge part of the pick work of the todo list, one commit at
> a time. If I'm wrong about this, I'd love pointers; what follows may
> still be interesting anyway.

I don't have a concrete alternative (yet?) but here are some pointers
to two alternate merge-without-touching-working-tree possibilities, if
your current route doesn't pan out as well as you like:

I posted some patches last year to make merge-recursive.c be able to
do merges without touching the working tree.  Adding a few flags would
then enable it for any of 'merge', 'cherry-pick', 'am', or
'rebase'...though for unsuccessful merges, there's a clear question of
what/how conflicts should be reported to the user.  That probably
depends a fair amount on the precise use-case.

Although that series was placed on the backburner due to the immediate
driver of the feature going away, I'm still interested in such a
change, though I think it would fall out as a nice side effect of
implementing Junio's proposed ideal-world-merge-recursive rewrite[1].
I have started looking into that[2], but no guarantees about how
quickly I'll find time to finish or even whether I will.

[1] https://public-inbox.org/git/xmqqd147kpdm.fsf@gitster.mtv.corp.google.com
[2] https://github.com/newren/git/blob/ort/ort-cover-letter contains
overview of ideas and notes to myself about what I was hoping to
accomplish; currently it doesn't even compile or do anything

> 4. API suggestion
>
> Here's what I really want 'git merge-tree' to output. :)
...
> If the merge had conflicts, write the "as merged as possible" tree to

You'd need to define "as merged as possible" more carefully, because I
thought you meant a tree containing all the three-way merge conflict
markers and such being present in the "resolved" file, but from your
parenthetical note below it appears you think that is a different tree
that would also be useful to diff against the first one.  That leaves
me wondering what the first tree is. (Is it just the tree where for
each path, if that path had no conflicts associated with it then it's
the merge-resolved-file, and otherwise it's the file contents from the
merge-base?).

Both of these trees are actually rather non-trivial to define.  The
wording above isn't actually sufficient, because content conflicts
aren't the only kind of conflict.  More on that below.

There is already a bunch of code in merge-recursive.c to create a
forcibly-merged-accepting-conflict-markers-in-the-resolution and
record it as a tree (this is used for creating virtual merge bases in
the recursive case, namely when there isn't a single merge-base for
the two branches you are merging).  It might be reusable for what you
want here, but it's not immediately clear whether all the things it
does are appropriate; someone would have to consider the non-content
(path-based) conflicts carefully.

> the object database and give me its sha, and then also give me the
> three-way merge diff output for all conflicts, as a regular patch
> against that tree, using full path names and shas. (Alternatively,
> maybe better, give me a second sha for a tree containing all the
> three-way merge diff patches applied, which I can diff against the
> first tree to find the conflict patches.)

As far as I can tell, you're assuming that it's possible with two
trees that are crafted "just right", that you can tell where the merge
conflicts are, with binary files being your only difficulty.  Content
conflicts aren't the only type that exist; there are also path-based
conflicts.  These type of conflicts also make it difficult to know how
the two trees you are requesting should even be created.

For example, if there is a modify/delete conflict, how can that be
determined from just two trees?  If the first tree has the base
version of the file, then the second tree either has a file at the
same position or it doesn't.  Neither case looks like a conflict, but
the original merge had one.  You need more information.  The exact
same thing can be said for rename/delete conflicts.

Similarly, rename/add (one side renames an existing file to some new
path (say, "new_path"), and the other adds a brand new file at
"new_path), or rename/rename(2to1) (each side renames a different file
to the same location), won't be detectable just by diffing two trees.
These are often handled by moving both files to some other location,
so there's no way to record in a tree that there was a conflict.

rename/rename(1to2) is similar, but instead of two different original
files being renamed to the same thing, this is one file being renamed
differently on different sides of history.

I know that several of the examples above involved rename detection,
which git-merge-trees won't even do, but that means you're even more
likely to face the modify/delete conflict cases.  And our list still
isn't done, either:

Directory/file conflicts (one side puts a directory of the same name
that the other side adds as a file) will also cause problems.

Finally, directory rename detection (currently in pu under review)
adds a few "implicit dir rename" conflict types (renames of multiple
directories would cause multiple files to be renamed to the same
location, or an existing file/dir being in the way of one or more
path(s) getting implicitly renamed).  This means that the number of
types of non-textual conflicts might also grow in the future so it may
be unwise to try to special case existing exceptions with a bag of
clever workarounds.


Hope that helps,
Elijah

  parent reply	other threads:[~2018-01-22 17:58 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-01-21  3:00 git merge-tree: bug report and some feature requests Josh Bleecher Snyder
2018-01-21  8:14 ` Ævar Arnfjörð Bjarmason
2018-01-22 17:58 ` Elijah Newren [this message]
2018-01-23  7:08   ` Josh Bleecher Snyder
2018-01-23 11:52     ` Edward Thomson
2018-01-24 18:46       ` Josh Bleecher Snyder
2018-01-24 19:39       ` Elijah Newren

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CABPp-BGYs9jo16OZR8NsL-eO9LwEttBxBspvp1-_JjuD2oBYbA@mail.gmail.com \
    --to=newren@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=josharian@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).