[PATCH 0/8] "git apply --threeway"

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

 



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
--
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]