git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Junio C Hamano <gitster@pobox.com>
To: git@vger.kernel.org
Subject: [PATCH 0/8] "git apply --threeway"
Date: Wed,  9 May 2012 23:02:17 -0700	[thread overview]
Message-ID: <1336629745-22436-1-git-send-email-gitster@pobox.com> (raw)

This series teaches "git apply" the same "three-way merge fallback" logic
that makes "am -3" so useful when flipping patches around.  For people who
do not know how "am -3" magic works, the basic idea goes like this:

 0) Suppose you have this history leading to commit E:

        O---A---B---...---E

 1) Also suppose you have a patch that is based on an older version; it no
    longer applies to the version of the file you have.  The patch would
    apply cleanly to the file in an older version, say A, and would result
    in file in a fictitious version X:

              X
             /
        O---A---B---...---E

    You can think of X as a commit where this patch was taken from, but
    there may not be any such commit in your object database.

 2) A useful observation to make here is that the result of applying such
    a patch to your current version should look similar to the result of
    merging X and E:

              X-------------M merge!
             /             /
        O---A---B---...---E

And this feature works exactly like that.

 - After trying and failing to apply the patch text, we inspect our object
   database and see if there is a blob object that matches what is
   recorded on the "index" line of the patch as its preimage.  We may not
   have such a blob object, and we give up in such a case.

 - And then we try to apply the patch text to that blob.  This also could
   fail, as the patch author could have tweaked the patch text after
   producing the patch with "git diff" without adjusting the "index" line.
   Again we simply give up in such a case.

 - When we successfully apply the patch to the older blob, the result
   would be what would appear in the fictitious commit X in the above
   picture.  We then try the usual file-level three-way merge between X
   and E using A as the base version.  This could cleanly merge, in which
   case we successfully applied the patch.  Or this could conflict, in
   which case we record the conflicted stages in the index, just like a
   conflicted "merge" or an "am -3" does, and leave the conflict markers
   in the result.

I've wanted to see this for the past few years, and even suggested that
this is a good bite-sized GSoC project, but unfortunately nobody bit it;
you have to do it yourself if you really want it, I guess.

Note that this iteration still does not do a few things:

 - We probably should call into the rerere machinery to have it help the
   user deal with the conflicts.

 - The "--threeway" option probably should be made explicitly incompatible
   with the "--reject" option (implement it when the command line is
   parsed).

 - It might make sense to make "--threeway" imply "--index", but it is not
   strictly necessary (see the second test case in t4108).

 - Documentation updates are missing.

 - "am -3" should be rewritten by using this.  That in turn means that the
   "--build-fake-ancestor" option of "git apply" will lose the only and
   the last in-tree user, but we may not be able to drop it immediately as
   there may be out-of-tree users.  On the other hand, any out-of-tree
   user that uses the "--build-fake-ancestor" option is reimplementing the
   three-way fallback on their own, and they can be updated to use the new
   "--threeway" option of "git apply".

 - Once this proves useful, it may deserve to use short-and-sweet "-3"
   option.

Junio C Hamano (8):
  apply: reformat comment
  apply: accept --threeway command line option
  apply: split load_preimage() helper function out
  apply: clear_image() clears things a bit more
  apply: refactor read_file_or_gitlink()
  apply: fall back on three-way merge
  apply: plug the three-way merge logic in
  apply: register conflicted stages to the index

 builtin/apply.c           | 198 +++++++++++++++++++++++++++++++++++++++++-----
 t/t4108-apply-threeway.sh |  78 ++++++++++++++++++
 2 files changed, 257 insertions(+), 19 deletions(-)
 create mode 100755 t/t4108-apply-threeway.sh

-- 
1.7.10.1.562.gfc79b1c

             reply	other threads:[~2012-05-10  6:02 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-05-10  6:02 Junio C Hamano [this message]
2012-05-10  6:02 ` [PATCH 1/8] apply: reformat comment Junio C Hamano
2012-05-10  6:02 ` [PATCH 2/8] apply: accept --threeway command line option Junio C Hamano
2012-05-10 12:40   ` Nguyen Thai Ngoc Duy
2012-05-10 15:31     ` Junio C Hamano
2012-05-10  6:02 ` [PATCH 3/8] apply: split load_preimage() helper function out Junio C Hamano
2012-05-10  6:02 ` [PATCH 4/8] apply: clear_image() clears things a bit more Junio C Hamano
2012-05-10  6:02 ` [PATCH 5/8] apply: refactor read_file_or_gitlink() Junio C Hamano
2012-05-10  6:02 ` [PATCH 6/8] apply: fall back on three-way merge Junio C Hamano
2012-05-10  7:26   ` Matthieu Moy
2012-05-10 15:10     ` Junio C Hamano
2012-05-10 15:41       ` Matthieu Moy
2012-05-10 20:31   ` Jeff King
2012-05-10 21:06     ` Junio C Hamano
2012-05-10 22:24       ` Jeff King
2012-05-10  6:02 ` [PATCH 7/8] apply: plug the three-way merge logic in Junio C Hamano
2012-05-10  6:02 ` [PATCH 8/8] apply: register conflicted stages to the index Junio C Hamano
2012-05-10  7:31 ` [PATCH 0/8] "git apply --threeway" Matthieu Moy
2012-05-10 15:26   ` Junio C Hamano

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=1336629745-22436-1-git-send-email-gitster@pobox.com \
    --to=gitster@pobox.com \
    --cc=git@vger.kernel.org \
    /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).