Originally, with no base, Git gave P4Merge $LOCAL as a dummy base:

   p4merge "$LOCAL" "$LOCAL" "$REMOTE" "$MERGED"

Commit 0a0ec7bd changed this to:

   p4merge "empty file" "$LOCAL" "$REMOTE" "$MERGED"

to avoid the problem of being unable to save in some circumstances.

Unfortunately this approach does not produce good results at all on
differing inputs. P4Merge really regards the blank file as the base, and
once you have just a couple of differences between the two branches you
end up with one a massive full-file conflict. The diff is not readable,
and you have to invoke "difftool MERGE_HEAD HEAD" manually to see a
2-way diff.

The original form appears to have invoked special 2-way comparison
behaviour that occurs only if the base filename is "" or equal to the
left input.  You get a good diff, and it does not auto-resolve in one
direction or the other. (Normally if one branch equals the base, it
would autoresolve to the other branch).

But there appears to be no way of getting this 2-way behaviour and being
able to reliably save. Having base=left appears to be triggering other
assumptions. There are tricks the user can use to force the save icon
on, but it's not intuitive.

So we now follow a suggestion given in the original patch's discussion:
generate a virtual base, consisting of the lines common to the two
branches. It produces a much nicer 3-way diff view than either of the
original forms, and than I suspect other mergetools are managing.

Signed-off-by: Kevin Bracey <ke...@bracey.fi>
 git-mergetool--lib.sh | 14 ++++++++++++++
 mergetools/p4merge    |  2 +-
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/git-mergetool--lib.sh b/git-mergetool--lib.sh
index e338be5..5b60cf5 100644
--- a/git-mergetool--lib.sh
+++ b/git-mergetool--lib.sh
@@ -108,6 +108,20 @@ check_unchanged () {
+make_virtual_base() {
+               # Copied from git-merge-one-file.sh.
+               # This starts with $LOCAL, and uses git apply to
+               # remove lines that are not in $REMOTE.
+               cp -- "$LOCAL" "$BASE"
+               sz0=`wc -c <"$BASE"`
+               @@DIFF@@ -u -L"a/$BASE" -L"b/$BASE" "$BASE" "$REMOTE" | git 
apply --no-add
+               sz1=`wc -c <"$BASE"`
+               # If we do not have enough common material, it is not
+               # worth trying two-file merge using common subsections.
+               expr $sz0 \< $sz1 \* 2 >/dev/null || : >"$BASE"
 valid_tool () {
        setup_tool "$1" && return 0
        cmd=$(get_merge_tool_cmd "$1")
diff --git a/mergetools/p4merge b/mergetools/p4merge
index 46b3a5a..f0a893b 100644
--- a/mergetools/p4merge
+++ b/mergetools/p4merge
@@ -21,7 +21,7 @@ diff_cmd () {
 merge_cmd () {
        touch "$BACKUP"
-       $base_present || >"$BASE"
+       $base_present || make_virtual_base
        "$merge_tool_path" "$BASE" "$REMOTE" "$LOCAL" "$MERGED"

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

Reply via email to