0

This question shows many good ways to use git-mergetool to show the condition of files before a merge commit using meld:

Setting up and using Meld as your Git difftool and mergetool

I like the three-panel form with $BASE in the middle panel.

When I inspect the result of a merge after a commit I'd like to see about the same thing, but with the results of the merge ($MERGED of git-mergetool) in the middle pane.

Is there any existing way to coax git into showing this, or do I need to roll my own? Note that I'm not interested in the "combined" diff offered by e.g. git show.

6
  • The question makes no sense. git-mergetool doesn't perform a merge, and knows nothing what happened as a result of a merge. After a successful merge, assuming you didn't fast-forward, the three commits that describe "about the same thing" (whatever you mean by that) are presumably: the merge commit (@), the merge commit's first parent (@^), and the merge commit's second parent (@^^). I don't know what problem you're trying to solve, but git is already "showing this" in the sense that the diffs are readily available, so surely you can take it from there. Commented Apr 30 at 17:10
  • 1
    The interesting thing about a post-merge IMO are the merge conflicts: git show --remerge-diff. Is that what you’re after? Commented Apr 30 at 18:41
  • I'm sorry you don't understand but it's really pretty obvious. You're right it's not too hard to do I'll just make an answer that shows then you'll understand :) Commented Apr 30 at 22:08
  • @Guildenstern that sounds close but I think it sounds like it's still going to be a two-pane diff when it gets to meld. That's from reading the man page though, when I try it (i.e. when I add --remerge-diff into git show <merge_commit>) for some reason I don't get shown a diff at all anymore but instead a log entry. Apparently I'm not using it right. Commented May 1 at 9:35
  • I posted an answer which I think should clarify everything. If any downvotes (or @matt :) want to suggest a different question that would be clearer I'm open to suggestions. I still think it's clear given the context (coming from the question linked at the start of the question) but maybe it otherwise isn't. Commented May 1 at 20:28

1 Answer 1

0

Here's a script that does it for an individual file which is enough for me. It wouldn't be hard to generalize to dirs.

#!/usr/bin/perl -w

# Given a two-parent merge <commit> and a path to a non-dir file in
# the repo, show the merge of that file in the commit in meld as a
# 3-way diff (symmetric to what `get mergetool --tool meld' shows
# before the merge, i.e. with the finished $MERGED result where $BASE
# would be in the mergetool display).  This follows from this question:
# https://stackoverflow.com/questions/34119866/setting-up-and-using-meld-as-your-git-difftool-and-mergetool
#
# The idea is to work around the fact that git mergetool is aware of
# diff3-type features of e.g. meld but all the git-diff stuff (including
# git-difftoot and git-show) is determinedly unaware and instead shows
# various worse 2-pane renderings of what happened.

@ARGV == 2 or die "wrong number of arguments";

my ($commit, $path) = @ARGV;

# Trees aren't supported yet
`git cat-file -t $commit:$path` eq "blob\n"
    or die "git cat-file -t doesn't think $commit:$path is a blob";

# Use our own subdir of /tmp to avoid littering /tmp too much
my $tdd = "/tmp/show_merge_with_3_pane_meld.perl.scratch";
-d $tdd or mkdir $tdd or die "mkdir $tdd failed: $!";

# Unpack versions of file into temporary files
my $cap = `git rev-list -n 1 --parents $commit`;   # Commit And Parents
$? == 0 or die "git rev-list command failed";
my @cap = map { chomp $_; $_ } split(' ', $cap);
@cap == 3
    or die "unexpected number of words in rev-list output, maybe $commit is ".
           "not a two-parent merge commit?";
my %cap = ( merged => $cap[0], p1 => $cap[1], p2 => $cap[2] );
my %tf = ();   # Temp Files (final names in $tdd to be given to meld)
while ( my ($key, $val) = each %cap ) {
    my $tfn = `git unpack-file $val:$path`;   # Temp File Name
    $? == 0 or die "git unpack-file command failed";
    chomp($tfn);
    # Verify temp file name form from git-unpack-file and save random part
    $tfn =~ m/^\.merge_file_(.*)$/
        or die "git unpack-file output doesn't match the expected pattern";
    my $tfn_rp = $1;   # Temp File Name Random Part
    my $otfn = "$key.$tfn_rp";   # Our Temp File Name
    # Move to our dir, rename
    not system("mv $tfn $tdd/$otfn") or die "mv command failed";
    $tf{$key} = $otfn;
}

# Display the merge
not system("cd $tdd && meld $tf{p1} $tf{merged} $tf{p2}")
    or die "cd or meld command failed";

# Uncomment if clean-up of temp files is desired
#unlink(map { "$tdd/$_" } values(%tf)) == 3 or die;
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.